home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 24 / CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso / CUCD / Utilities / vim-5.1 / src / ex_docmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-06  |  123.3 KB  |  5,661 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8.  
  9. /*
  10.  * ex_docmd.c: functions for executing an Ex command line.
  11.  */
  12.  
  13. #include "vim.h"
  14.  
  15. #define DO_DECLARE_EXCMD
  16. #include "ex_cmds.h"    /* Declare the cmdnames struct. */
  17.  
  18. #ifdef HAVE_FCNTL_H
  19. # include <fcntl.h>        /* for chdir() */
  20. #endif
  21.  
  22. static int        quitmore = 0;
  23. static int        ex_pressedreturn = FALSE;
  24.  
  25. #ifdef WANT_EVAL
  26. /*
  27.  * For conditional commands a stack is kept of nested conditionals.
  28.  * When cs_idx < 0, there is no conditional command.
  29.  */
  30. #define CSTACK_LEN    50
  31.  
  32. struct condstack
  33. {
  34.     char    cs_flags[CSTACK_LEN];   /* CSF_ flags */
  35.     int        cs_line[CSTACK_LEN];    /* line number of ":while" line */
  36.     int        cs_idx;            /* current entry, or -1 if none */
  37.     int        cs_whilelevel;        /* number of nested ":while"s */
  38.     char    cs_had_while;        /* just found ":while" */
  39.     char    cs_had_continue;        /* just found ":continue" */
  40.     char    cs_had_endwhile;        /* just found ":endwhile" */
  41. };
  42.  
  43. #define CSF_TRUE    1    /* condition was TRUE */
  44. #define CSF_ACTIVE    2    /* current state is active */
  45. #define CSF_WHILE    4    /* is a ":while" */
  46. #endif
  47.  
  48. #ifdef WANT_EVAL
  49. static void free_cmdlines __ARGS((struct growarray *gap));
  50. static char_u    *do_one_cmd __ARGS((char_u **, int, struct condstack *, char_u *(*getline)(int, void *, int), void *cookie));
  51. #else
  52. static char_u    *do_one_cmd __ARGS((char_u **, int, char_u *(*getline)(int, void *, int), void *cookie));
  53. #endif
  54. static int    buf_write_all __ARGS((BUF *));
  55. static int    do_write __ARGS((EXARG *eap));
  56. static char_u    *getargcmd __ARGS((char_u **));
  57. static char_u    *skip_cmd_arg __ARGS((char_u *p));
  58. #ifdef QUICKFIX
  59. static void    do_make __ARGS((char_u *));
  60. static char_u    *get_mef_name __ARGS((int newname));
  61. static void    do_cfile __ARGS((EXARG *eap));
  62. #endif
  63. static int    do_arglist __ARGS((char_u *));
  64. static int    rem_backslash __ARGS((char_u *str));
  65. static int    check_readonly __ARGS((int));
  66. static int    check_changed __ARGS((BUF *, int, int, int));
  67. static int    check_more __ARGS((int, int));
  68. static linenr_t get_address __ARGS((char_u **));
  69. static void    do_quit __ARGS((EXARG *eap));
  70. static void    do_quit_all __ARGS((int forceit));
  71. static void    do_close __ARGS((EXARG *eap));
  72. static void    do_suspend __ARGS((int forceit));
  73. static void    do_exit __ARGS((EXARG *eap));
  74. static void    do_wqall __ARGS((EXARG *eap));
  75. static void    do_print __ARGS((EXARG *eap));
  76. static void    do_argfile __ARGS((EXARG *eap, int argn));
  77. static void    do_next __ARGS((EXARG *eap));
  78. static void    do_recover __ARGS((EXARG *eap));
  79. static void    do_args __ARGS((EXARG *eap));
  80. static void    do_wnext __ARGS((EXARG *eap));
  81. static void    do_resize __ARGS((EXARG *eap));
  82. static void    do_splitview __ARGS((EXARG *eap));
  83. static void    do_exedit __ARGS((EXARG *eap, WIN *old_curwin));
  84. #ifdef USE_GUI
  85. static void    do_gui __ARGS((EXARG *eap));
  86. #endif
  87. static void    do_swapname __ARGS((void));
  88. static void    do_read __ARGS((EXARG *eap));
  89. static void    do_cd __ARGS((EXARG *eap));
  90. static void    do_pwd __ARGS((void));
  91. static void    do_sleep __ARGS((EXARG *eap));
  92. static void    do_exmap __ARGS((EXARG *eap, int isabbrev));
  93. static void    do_winsize __ARGS((char_u *arg));
  94. static void    do_exops __ARGS((EXARG *eap));
  95. static void    do_copymove __ARGS((EXARG *eap));
  96. static void    do_exjoin __ARGS((EXARG *eap));
  97. static void    do_exat __ARGS((EXARG *eap));
  98. static void    do_redir __ARGS((EXARG *eap));
  99. static void    close_redir __ARGS((void));
  100. static void    do_mkrc __ARGS((EXARG *eap));
  101. static FILE    *open_exfile __ARGS((EXARG *eap, char *mode));
  102. static void    do_setmark __ARGS((EXARG *eap));
  103. #ifdef EX_EXTRA
  104. static void    do_normal __ARGS((EXARG *eap));
  105. #endif
  106. #ifdef FIND_IN_PATH
  107. static char_u    *do_findpat __ARGS((EXARG *eap, int action));
  108. #endif
  109. static void    do_ex_tag __ARGS((EXARG *eap, int dt));
  110. #ifdef WANT_EVAL
  111. static char_u    *do_if __ARGS((EXARG *eap, struct condstack *cstack));
  112. static char_u    *do_else __ARGS((EXARG *eap, struct condstack *cstack));
  113. static char_u    *do_while __ARGS((EXARG *eap, struct condstack *cstack));
  114. static char_u    *do_continue __ARGS((struct condstack *cstack));
  115. static char_u    *do_break __ARGS((struct condstack *cstack));
  116. static char_u    *do_endwhile __ARGS((struct condstack *cstack));
  117. static int    has_while_cmd __ARGS((char_u *p));
  118. #endif
  119.  
  120. /*
  121.  * Table used to quickly search for a command, based on its first character.
  122.  */
  123. CMDIDX cmdidxs[27] =
  124. {
  125.     CMD_append,
  126.     CMD_buffer,
  127.     CMD_change,
  128.     CMD_delete,
  129.     CMD_edit,
  130.     CMD_file,
  131.     CMD_global,
  132.     CMD_help,
  133.     CMD_insert,
  134.     CMD_join,
  135.     CMD_k,
  136.     CMD_list,
  137.     CMD_move,
  138.     CMD_next,
  139.     CMD_open,
  140.     CMD_print,
  141.     CMD_quit,
  142.     CMD_read,
  143.     CMD_substitute,
  144.     CMD_t,
  145.     CMD_undo,
  146.     CMD_vglobal,
  147.     CMD_write,
  148.     CMD_xit,
  149.     CMD_yank,
  150.     CMD_z,
  151.     CMD_Next
  152. };
  153.  
  154. /*
  155.  * do_exmode(): Repeatedly get commands for the "Ex" mode, until the ":vi"
  156.  * command is given.
  157.  */
  158.     void
  159. do_exmode()
  160. {
  161.     int        save_msg_scroll;
  162.     int        prev_msg_row;
  163.     linenr_t    prev_line;
  164.  
  165.     save_msg_scroll = msg_scroll;
  166.     ++RedrawingDisabled;        /* don't redisplay the window */
  167.     ++no_wait_return;            /* don't wait for return */
  168.     settmode(TMODE_COOK);
  169.  
  170.     State = NORMAL;
  171.     exmode_active = TRUE;
  172. #ifdef USE_SNIFF
  173.     want_sniff_request = 0;    /* No K_SNIFF wanted */
  174. #endif
  175.  
  176.     MSG("Entering Ex mode.  Type \"visual\" to get out.");
  177.     while (exmode_active)
  178.     {
  179.  
  180.     msg_scroll = TRUE;
  181.     need_wait_return = FALSE;
  182.     ex_pressedreturn = FALSE;
  183.     ex_no_reprint = FALSE;
  184.     prev_msg_row = msg_row;
  185.     prev_line = curwin->w_cursor.lnum;
  186. #ifdef USE_SNIFF
  187.     ProcessSniffRequests();
  188. #endif
  189.     do_cmdline(NULL, getexmodeline, NULL, DOCMD_NOWAIT);
  190.     lines_left = Rows - 1;
  191.  
  192.     if (prev_line != curwin->w_cursor.lnum && !ex_no_reprint)
  193.     {
  194.         if (ex_pressedreturn)
  195.         {
  196.         /* go up one line, to overwrite the ":<CR>" line, so the
  197.          * output doensn't contain empty lines. */
  198.         msg_row = prev_msg_row;
  199.         if (prev_msg_row == Rows - 1)
  200.             msg_row--;
  201.         }
  202.         msg_col = 0;
  203.         print_line_no_prefix(curwin->w_cursor.lnum, FALSE);
  204.         msg_clr_eos();
  205.     }
  206.     else if (ex_pressedreturn)    /* must be at EOF */
  207.         EMSG("At end-of-file");
  208.     }
  209.  
  210.     settmode(TMODE_RAW);
  211.     --RedrawingDisabled;
  212.     --no_wait_return;
  213.     update_screen(CLEAR);
  214.     need_wait_return = FALSE;
  215.     msg_scroll = save_msg_scroll;
  216. }
  217.  
  218. /*
  219.  * do_cmdline(): execute one Ex command line
  220.  *
  221.  * 1. Execute "cmdline" when it is not NULL.
  222.  *    If "cmdline" is NULL, or more lines are needed, getline() is used.
  223.  * 2. Split up in parts separated with '|'.
  224.  *
  225.  * This function can be called recursively!
  226.  *
  227.  * flags:
  228.  * DOCMD_VERBOSE - The command will be included in the error message.
  229.  * DOCMD_NOWAIT  - Don't call wait_return() and friends.
  230.  * DOCMD_REPEAT  - Repeat execution until getline() returns NULL.
  231.  *
  232.  * return FAIL if cmdline could not be executed, OK otherwise
  233.  */
  234.     int
  235. do_cmdline(cmdline, getline, cookie, flags)
  236.     char_u    *cmdline;
  237.     char_u    *(*getline) __ARGS((int, void *, int));
  238.     void    *cookie;        /* argument for getline() */
  239.     int        flags;
  240. {
  241.     char_u    *next_cmdline;        /* next cmd to execute */
  242.     char_u    *cmdline_copy = NULL;    /* copy of cmd line */
  243.     static int    recursive = 0;        /* recursive depth */
  244.     int        msg_didout_before_start = 0;
  245.     int        count = 0;        /* line number count */
  246.     int        did_inc = FALSE;    /* incremented RedrawingDisabled */
  247.     int        retval = OK;
  248. #ifdef WANT_EVAL
  249.     struct condstack cstack;        /* conditional stack */
  250.     struct growarray lines_ga;        /* keep lines for ":while" */
  251.     int        current_line = 0;    /* active line in lines_ga */
  252.     int        did_endwhile = FALSE;    /* ended with ":endwhile" */
  253. #endif
  254.  
  255. #ifdef WANT_EVAL
  256.     cstack.cs_idx = -1;
  257.     cstack.cs_whilelevel = 0;
  258.     cstack.cs_had_while = FALSE;
  259.     cstack.cs_had_endwhile = FALSE;
  260.     cstack.cs_had_continue = FALSE;
  261.     ga_init(&lines_ga);
  262.     lines_ga.ga_itemsize = sizeof(char_u *);
  263.     lines_ga.ga_growsize = 10;
  264. #endif
  265.  
  266.     /*
  267.      * "did_emsg" will be set to TRUE when emsg() is used, in which case we
  268.      * cancel the whole command line, and any if/endif while/endwhile loop.
  269.      */
  270.     did_emsg = FALSE;
  271.  
  272.     /*
  273.      * Continue executing command lines:
  274.      * - when inside an ":if" or ":while"
  275.      * - for multiple commands on one line, separated with '|'
  276.      * - when repeating until there are no more lines (for ":source")
  277.      */
  278.     next_cmdline = cmdline;
  279.     do
  280.     {
  281.     /* stop skipping cmds for an error msg after all endifs and endwhiles */
  282.     if (next_cmdline == NULL
  283. #ifdef WANT_EVAL
  284.                 && cstack.cs_idx < 0
  285. #endif
  286.                             )
  287.         did_emsg = FALSE;
  288.  
  289.     /*
  290.      * 1. If repeating a line with ":while", get a line from lines_ga.
  291.      * 2. If no line given: Get an allocated line with getline().
  292.      * 3. If a line is given: Make a copy, so we can mess with it.
  293.      */
  294.  
  295. #ifdef WANT_EVAL
  296.     /* 1. If repeating, get a previous line from lines_ga. */
  297.     if (cstack.cs_whilelevel && current_line < lines_ga.ga_len)
  298.     {
  299.         /* Each '|' separated command is stored separately in lines_ga, to
  300.          * be able to jump to it.  Don't use next_cmdline now. */
  301.         vim_free(cmdline_copy);
  302.         cmdline_copy = NULL;
  303.         next_cmdline = ((char_u **)(lines_ga.ga_data))[current_line];
  304.         line_breakcheck();        /* check if CTRL-C typed */
  305.     }
  306. #endif
  307.  
  308.     /* 2. If no line given, get an allocated line with getline(). */
  309.     if (next_cmdline == NULL)
  310.     {
  311.         /*
  312.          * Need to set msg_didout for the first line after an ":if",
  313.          * otherwise the ":if" will be overwritten.
  314.          */
  315.         if (count == 1 && getline == getexline)
  316.         msg_didout = TRUE;
  317.         if (getline == NULL || (next_cmdline = getline(':', cookie,
  318. #ifdef WANT_EVAL
  319.             cstack.cs_idx < 0 ? 0 : (cstack.cs_idx + 1) * 2
  320. #else
  321.             0
  322. #endif
  323.                 )) == NULL)
  324.         {
  325.         /* don't call wait_return for aborted command line */
  326.         if (KeyTyped)
  327.             need_wait_return = FALSE;
  328.         retval = FAIL;
  329.         break;
  330.         }
  331.     }
  332.  
  333.     /* 3. Make a copy of the command so we can mess with it. */
  334.     else if (cmdline_copy == NULL)
  335.     {
  336.         next_cmdline = vim_strsave(next_cmdline);
  337.         if (next_cmdline == NULL)
  338.         {
  339.         retval = FAIL;
  340.         break;
  341.         }
  342.     }
  343.     cmdline_copy = next_cmdline;
  344.  
  345. #ifdef WANT_EVAL
  346.     /*
  347.      * Save the current line when inside a ":while", and when the command
  348.      * looks like a ":while", because we may need it later.
  349.      * When there is a '|' and another command, it is stored separately,
  350.      * because we need to be able to jump back to it from an :endwhile.
  351.      */
  352.     if (       current_line == lines_ga.ga_len
  353.         && (cstack.cs_whilelevel || has_while_cmd(next_cmdline))
  354.         && ga_grow(&lines_ga, 1) == OK)
  355.     {
  356.         ((char_u **)(lines_ga.ga_data))[current_line] =
  357.                             vim_strsave(next_cmdline);
  358.         ++lines_ga.ga_len;
  359.         --lines_ga.ga_room;
  360.     }
  361.     did_endwhile = FALSE;
  362. #endif
  363.  
  364.     if (count++ == 0)
  365.     {
  366.         /*
  367.          * All output from the commands is put below each other, without
  368.          * waiting for a return. Don't do this when executing commands
  369.          * from a script or when being called recursive (e.g. for ":e
  370.          * +command file").
  371.          */
  372.         if (!(flags & DOCMD_NOWAIT) && !recursive)
  373.         {
  374.         msg_didout_before_start = msg_didout;
  375.         msg_didany = FALSE; /* no output yet */
  376.         msg_start();
  377.         msg_scroll = TRUE;  /* put messages below each other */
  378.         ++no_wait_return;   /* dont wait for return until finished */
  379.         ++RedrawingDisabled;
  380.         did_inc = TRUE;
  381.         }
  382.     }
  383.  
  384.     /*
  385.      * 2. Execute one '|' separated command.
  386.      *    do_one_cmd() will return NULL if there is no trailing '|'.
  387.      *    "cmdline_copy" can change, e.g. for '%' and '#' expansion.
  388.      */
  389.     ++recursive;
  390.     next_cmdline = do_one_cmd(&cmdline_copy, flags & DOCMD_VERBOSE,
  391. #ifdef WANT_EVAL
  392.                 &cstack,
  393. #endif
  394.                 getline, cookie);
  395.     --recursive;
  396.     if (next_cmdline == NULL)
  397.     {
  398.         vim_free(cmdline_copy);
  399.         cmdline_copy = NULL;
  400.  
  401.         /*
  402.          * If the command was typed, remember it for the ':' register.
  403.          * Do this AFTER executing the command to make :@: work.
  404.          */
  405.         if (getline == getexline && new_last_cmdline != NULL)
  406.         {
  407.         vim_free(last_cmdline);
  408.         last_cmdline = new_last_cmdline;
  409.         new_last_cmdline = NULL;
  410.         }
  411.     }
  412.     else
  413.     {
  414.         /* need to copy the command after the '|' to cmdline_copy, for the
  415.          * next do_one_cmd() */
  416.         STRCPY(cmdline_copy, next_cmdline);
  417.         next_cmdline = cmdline_copy;
  418.     }
  419.  
  420.  
  421. #ifdef WANT_EVAL
  422.     if (cstack.cs_whilelevel)
  423.     {
  424.         ++current_line;
  425.  
  426.         /*
  427.          * An ":endwhile" and ":continue" is handled here.
  428.          * If we were executing commands, jump back to the ":while".
  429.          * If we were not executing commands, decrement whilelevel.
  430.          */
  431.         if (cstack.cs_had_endwhile || cstack.cs_had_continue)
  432.         {
  433.         if (cstack.cs_had_endwhile)
  434.         {
  435.             cstack.cs_had_endwhile = FALSE;
  436.             did_endwhile = TRUE;
  437.         }
  438.         else
  439.             cstack.cs_had_continue = FALSE;
  440.  
  441.         /* jump back to the matching ":while"? */
  442.         if (!did_emsg && cstack.cs_idx >= 0
  443.             && (cstack.cs_flags[cstack.cs_idx] & CSF_ACTIVE))
  444.         {
  445.             current_line = cstack.cs_line[cstack.cs_idx];
  446.             cstack.cs_had_while = TRUE;        /* note we jumped there */
  447.         }
  448.         else /* can only get here with ":endwhile" */
  449.         {
  450.             --cstack.cs_whilelevel;
  451.             if (cstack.cs_idx >= 0)
  452.             --cstack.cs_idx;
  453.         }
  454.         }
  455.  
  456.         /*
  457.          * For a ":while" we need to remember the line number.
  458.          */
  459.         else if (cstack.cs_had_while)
  460.         {
  461.         cstack.cs_had_while = FALSE;
  462.         cstack.cs_line[cstack.cs_idx] = current_line - 1;
  463.         }
  464.     }
  465.  
  466.     /*
  467.      * When not inside a ":while", clear remembered lines.
  468.      */
  469.     if (!cstack.cs_whilelevel)
  470.     {
  471.         free_cmdlines(&lines_ga);
  472.         current_line = 0;
  473.     }
  474. #endif /* WANT_EVAL */
  475.  
  476.     }
  477.     /*
  478.      * Continue executing command lines when:
  479.      * - no CTRL-C typed
  480.      * - didn't get an error message or lines are not typed
  481.      * - there is a command after '|', inside a :if or :while, or looping for
  482.      *     ":source" command.
  483.      */
  484.     while (!got_int
  485.         && !(did_emsg && (getline == getexmodeline || getline == getexline))
  486.         && (next_cmdline != NULL
  487. #ifdef WANT_EVAL
  488.             || cstack.cs_idx >= 0
  489. #endif
  490.             || (flags & DOCMD_REPEAT)));
  491.  
  492.     vim_free(cmdline_copy);
  493. #ifdef WANT_EVAL
  494.     free_cmdlines(&lines_ga);
  495. #endif
  496.  
  497.     /*
  498.      * If there was too much output to fit on the command line, ask the user to
  499.      * hit return before redrawing the screen. With the ":global" command we do
  500.      * this only once after the command is finished.
  501.      */
  502.     if (did_inc)
  503.     {
  504.     --RedrawingDisabled;
  505.     --no_wait_return;
  506.     msg_scroll = FALSE;
  507.  
  508.     /*
  509.      * When just finished an ":if"-":else" which was typed, no need to
  510.      * wait for hit-return.  Also for an error situation.
  511.      */
  512.     if ((count > 1 && KeyTyped && !did_emsg
  513. #ifdef WANT_EVAL
  514.                 && !did_endwhile
  515. #endif
  516.                         ) || retval == FAIL)
  517.     {
  518.         need_wait_return = FALSE;
  519.         msg_didany = FALSE;        /* don't wait when restarting edit */
  520.         redraw_later(NOT_VALID);
  521.     }
  522.     else if ((need_wait_return || (msg_check() && !dont_wait_return)))
  523.     {
  524.         /*
  525.          * The msg_start() above clears msg_didout. The wait_return we do
  526.          * here should not overwrite the command that may be shown before
  527.          * doing that.
  528.          */
  529.         msg_didout = msg_didout_before_start;
  530.         wait_return(FALSE);
  531.     }
  532.     }
  533.  
  534.     return retval;
  535. }
  536.  
  537. #ifdef WANT_EVAL
  538.     static void
  539. free_cmdlines(gap)
  540.     struct growarray *gap;
  541. {
  542.     while (gap->ga_len)
  543.     {
  544.     vim_free(((char_u **)(gap->ga_data))[gap->ga_len - 1]);
  545.     --gap->ga_len;
  546.     ++gap->ga_room;
  547.     }
  548. }
  549. #endif
  550.  
  551. /*
  552.  * Execute one Ex command.
  553.  *
  554.  * If 'sourcing' is TRUE, the command will be included in the error message.
  555.  *
  556.  * 2. skip comment lines and leading space
  557.  * 3. parse range
  558.  * 4. parse command
  559.  * 5. parse arguments
  560.  * 6. switch on command name
  561.  *
  562.  * Note: "getline" can be NULL.
  563.  *
  564.  * This function may be called recursively!
  565.  */
  566.     static char_u *
  567. do_one_cmd(cmdlinep, sourcing,
  568. #ifdef WANT_EVAL
  569.                 cstack,
  570. #endif
  571.                     getline, cookie)
  572.     char_u        **cmdlinep;
  573.     int            sourcing;
  574. #ifdef WANT_EVAL
  575.     struct condstack    *cstack;
  576. #endif
  577.     char_u        *(*getline) __ARGS((int, void *, int));
  578.     void        *cookie;        /* argument for getline() */
  579. {
  580.     char_u        *p;
  581.     char_u        *new_cmdline;
  582.     int            i;
  583.     int            len;
  584.     long        argt;
  585.     linenr_t        lnum;
  586.     long        n;
  587.     char_u        *errormsg = NULL;    /* error message */
  588.     EXARG        ea;            /* Ex command arguments */
  589.  
  590.     vim_memset(&ea, 0, sizeof(ea));
  591.     ea.line1 = 1;
  592.     ea.line2 = 1;
  593.  
  594.     /* when not editing the last file :q has to be typed twice */
  595.     if (quitmore)
  596.     --quitmore;
  597. /*
  598.  * 2. skip comment lines and leading space and colons
  599.  */
  600.     for (ea.cmd = *cmdlinep; *ea.cmd == ' ' || *ea.cmd == '\t'
  601.                           || *ea.cmd == ':'; ea.cmd++)
  602.     ;
  603.  
  604.     /* in ex mode, an empty line works like :+ */
  605.     if (*ea.cmd == NUL && exmode_active && getline == getexmodeline)
  606.     {
  607.     ea.cmd = (char_u *)"+";
  608.     ex_pressedreturn = TRUE;
  609.     }
  610.  
  611.     if (*ea.cmd == '"' || *ea.cmd == NUL)   /* ignore comment and empty lines */
  612.     goto doend;
  613.  
  614. #ifdef WANT_EVAL
  615.     ea.skip = did_emsg || (cstack->cs_idx >= 0
  616.              && !(cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE));
  617. #endif
  618.  
  619. /*
  620.  * 3. parse a range specifier of the form: addr [,addr] [;addr] ..
  621.  *
  622.  * where 'addr' is:
  623.  *
  624.  * %          (entire file)
  625.  * $  [+-NUM]
  626.  * 'x [+-NUM] (where x denotes a currently defined mark)
  627.  * .  [+-NUM]
  628.  * [+-NUM]..
  629.  * NUM
  630.  *
  631.  * The ea.cmd pointer is updated to point to the first character following the
  632.  * range spec. If an initial address is found, but no second, the upper bound
  633.  * is equal to the lower.
  634.  */
  635.  
  636. #ifdef WANT_EVAL
  637.     if (ea.skip)
  638.     goto skip_address;
  639. #endif
  640.  
  641.     /* repeat for all ',' or ';' separated addresses */
  642.     for (;;)
  643.     {
  644.     ea.line1 = ea.line2;
  645.     ea.line2 = curwin->w_cursor.lnum;   /* default is current line number */
  646.     ea.cmd = skipwhite(ea.cmd);
  647.     lnum = get_address(&ea.cmd);
  648.     if (ea.cmd == NULL)            /* error detected */
  649.         goto doend;
  650.     if (lnum == MAXLNUM)
  651.     {
  652.         if (*ea.cmd == '%')            /* '%' - all lines */
  653.         {
  654.         ++ea.cmd;
  655.         ea.line1 = 1;
  656.         ea.line2 = curbuf->b_ml.ml_line_count;
  657.         ++ea.addr_count;
  658.         }
  659.         else if (*ea.cmd == '*')        /* '*' - visual area */
  660.         {
  661.         FPOS        *fp;
  662.  
  663.         ++ea.cmd;
  664.         fp = getmark('<', FALSE);
  665.         if (check_mark(fp) == FAIL)
  666.             goto doend;
  667.         ea.line1 = fp->lnum;
  668.         fp = getmark('>', FALSE);
  669.         if (check_mark(fp) == FAIL)
  670.             goto doend;
  671.         ea.line2 = fp->lnum;
  672.         ++ea.addr_count;
  673.         }
  674.     }
  675.     else
  676.         ea.line2 = lnum;
  677.     ea.addr_count++;
  678.  
  679.     if (*ea.cmd == ';')
  680.         curwin->w_cursor.lnum = ea.line2;
  681.     else if (*ea.cmd != ',')
  682.         break;
  683.     ++ea.cmd;
  684.     }
  685.  
  686.     /* One address given: set start and end lines */
  687.     if (ea.addr_count == 1)
  688.     {
  689.     ea.line1 = ea.line2;
  690.         /* ... but only implicit: really no address given */
  691.     if (lnum == MAXLNUM)
  692.         ea.addr_count = 0;
  693.     }
  694.  
  695.     /* Don't leave the cursor on an illegal line (caused by ';') */
  696.     check_cursor_lnum();
  697.  
  698. #ifdef WANT_EVAL
  699. skip_address:
  700. #endif
  701.  
  702. /*
  703.  * 4. parse command
  704.  */
  705.  
  706.     /*
  707.      * Skip ':' and any white space
  708.      */
  709.     ea.cmd = skipwhite(ea.cmd);
  710.     while (*ea.cmd == ':')
  711.     ea.cmd = skipwhite(ea.cmd + 1);
  712.  
  713.     /*
  714.      * If we got a line, but no command, then go to the line.
  715.      * If we find a '|' or '\n' we set ea.nextcmd.
  716.      */
  717.     if (*ea.cmd == NUL || *ea.cmd == '"' ||
  718.                    (ea.nextcmd = check_nextcmd(ea.cmd)) != NULL)
  719.     {
  720.     /*
  721.      * strange vi behaviour:
  722.      * ":3"        jumps to line 3
  723.      * ":3|..."    prints line 3
  724.      * ":|"        prints current line
  725.      */
  726. #ifdef WANT_EVAL
  727.     if (ea.skip)        /* skip this if inside :if */
  728.         goto doend;
  729. #endif
  730.     if (*ea.cmd == '|')
  731.     {
  732.         ea.cmdidx = CMD_print;
  733.         do_print(&ea);
  734.     }
  735.     else if (ea.addr_count != 0)
  736.     {
  737.         if (ea.line2 == 0)
  738.         curwin->w_cursor.lnum = 1;
  739.         else if (ea.line2 > curbuf->b_ml.ml_line_count)
  740.         curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  741.         else
  742.         curwin->w_cursor.lnum = ea.line2;
  743.         beginline(BL_SOL | BL_FIX);
  744.     }
  745.     goto doend;
  746.     }
  747.  
  748.     /*
  749.      * Isolate the command and search for it in the command table.
  750.      * Exeptions:
  751.      * - the 'k' command can directly be followed by any character.
  752.      * - the 's' command can be followed directly by 'c', 'g' or 'r'
  753.      *        but :sre[wind] is another command.
  754.      */
  755.     if (*ea.cmd == 'k')
  756.     {
  757.     ea.cmdidx = CMD_k;
  758.     p = ea.cmd + 1;
  759.     }
  760.     else if (ea.cmd[0] == 's'
  761.         && (ea.cmd[1] == 'c'
  762.         || ea.cmd[1] == 'g'
  763.         || (ea.cmd[1] == 'r' && ea.cmd[2] != 'e')))
  764.     {
  765.     ea.cmdidx = CMD_substitute;
  766.     p = ea.cmd + 1;
  767.     }
  768.     else
  769.     {
  770.     p = ea.cmd;
  771.     while (isalpha(*p))
  772.         ++p;
  773.     /* check for non-alpha command */
  774.     if (p == ea.cmd && vim_strchr((char_u *)"@!=><&~#", *p) != NULL)
  775.         ++p;
  776.     i = (int)(p - ea.cmd);
  777.  
  778.     if (*ea.cmd >= 'a' && *ea.cmd <= 'z')
  779.         ea.cmdidx = cmdidxs[*ea.cmd - 'a'];
  780.     else
  781.         ea.cmdidx = cmdidxs[26];
  782.  
  783.     for ( ; ea.cmdidx < CMD_SIZE; ea.cmdidx = (CMDIDX)((int)ea.cmdidx + 1))
  784.         if (STRNCMP(cmdnames[ea.cmdidx].cmd_name, (char *)ea.cmd,
  785.                                   (size_t)i) == 0)
  786.         break;
  787.     if (i == 0 || ea.cmdidx == CMD_SIZE)
  788.     {
  789. #ifdef WANT_EVAL
  790.         if (!ea.skip)
  791. #endif
  792.         {
  793.         STRCPY(IObuff, "Not an editor command");
  794.         if (!sourcing)
  795.         {
  796.             STRCAT(IObuff, ": ");
  797.             STRNCAT(IObuff, *cmdlinep, 40);
  798.         }
  799.         errormsg = IObuff;
  800.         }
  801.         goto doend;
  802.     }
  803.     }
  804.  
  805.     if (*p == '!' && ea.cmdidx != CMD_substitute)    /* forced commands */
  806.     {
  807.     ++p;
  808.     ea.forceit = TRUE;
  809.     }
  810.     else
  811.     ea.forceit = FALSE;
  812.  
  813. /*
  814.  * 5. parse arguments
  815.  */
  816.     argt = cmdnames[ea.cmdidx].cmd_argt;
  817.  
  818.     if (!(argt & RANGE) && ea.addr_count)    /* no range allowed */
  819.     {
  820.     errormsg = e_norange;
  821.     goto doend;
  822.     }
  823.  
  824.     if (!(argt & BANG) && ea.forceit)        /* no <!> allowed */
  825.     {
  826.     errormsg = e_nobang;
  827.     if (ea.cmdidx == CMD_help)
  828.         errormsg = (char_u *)"Don't panic!";
  829.     goto doend;
  830.     }
  831.  
  832.     /*
  833.      * If the range is backwards, ask for confirmation and, if given, swap
  834.      * ea.line1 & ea.line2 so it's forwards again.
  835.      * When global command is busy, don't ask, will fail below.
  836.      */
  837.     if (!global_busy && ea.line1 > ea.line2)
  838.     {
  839.     if (sourcing)
  840.     {
  841.         errormsg = (char_u *)"Backwards range given";
  842.         goto doend;
  843.     }
  844.     else if (ask_yesno((char_u *)
  845.                "Backwards range given, OK to swap", FALSE) != 'y')
  846.         goto doend;
  847.     lnum = ea.line1;
  848.     ea.line1 = ea.line2;
  849.     ea.line2 = lnum;
  850.     }
  851.     /*
  852.      * don't complain about the range if it is not used
  853.      * (could happen if line_count is accidently set to 0)
  854.      */
  855.     if (       ea.line1 < 0
  856.         || ea.line2 < 0
  857.         || ea.line1 > ea.line2
  858.         || ((argt & RANGE)
  859.         && !(argt & NOTADR)
  860.         && ea.line2 > curbuf->b_ml.ml_line_count))
  861.     {
  862.     errormsg = e_invrange;
  863.     goto doend;
  864.     }
  865.  
  866.     if ((argt & NOTADR) && ea.addr_count == 0)    /* default is 1, not cursor */
  867.     ea.line2 = 1;
  868.  
  869.     if (!(argt & ZEROR))        /* zero in range not allowed */
  870.     {
  871.     if (ea.line1 == 0)
  872.         ea.line1 = 1;
  873.     if (ea.line2 == 0)
  874.         ea.line2 = 1;
  875.     }
  876.  
  877. #ifdef QUICKFIX
  878.     /*
  879.      * For the :make command we insert the 'makeprg' option here,
  880.      * so things like % get expanded.
  881.      */
  882.     if (ea.cmdidx == CMD_make)
  883.     {
  884.     if ((new_cmdline = alloc((int)(STRLEN(p_mp) + STRLEN(p) + 2))) == NULL)
  885.         goto doend;            /* out of memory */
  886.     STRCPY(new_cmdline, p_mp);
  887.     STRCAT(new_cmdline, " ");
  888.     STRCAT(new_cmdline, p);
  889.     msg_make(p);
  890.     /* 'ea.cmd' is not set here, because it is not used at CMD_make */
  891.     vim_free(*cmdlinep);
  892.     *cmdlinep = new_cmdline;
  893.     p = new_cmdline;
  894.     }
  895. #endif
  896.  
  897.     /*
  898.      * Skip to start of argument.
  899.      * Don't do this for the ":!" command, because ":!! -l" needs the space.
  900.      */
  901.     if (ea.cmdidx == CMD_bang)
  902.     ea.arg = p;
  903.     else
  904.     ea.arg = skipwhite(p);
  905.  
  906.     if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update)
  907.     {
  908.     if (*ea.arg == '>')            /* append */
  909.     {
  910.         if (*++ea.arg != '>')        /* typed wrong */
  911.         {
  912.         errormsg = (char_u *)"Use w or w>>";
  913.         goto doend;
  914.         }
  915.         ea.arg = skipwhite(ea.arg + 1);
  916.         ea.append = TRUE;
  917.     }
  918.     else if (*ea.arg == '!' && ea.cmdidx == CMD_write)  /* :w !filter */
  919.     {
  920.         ++ea.arg;
  921.         ea.usefilter = TRUE;
  922.     }
  923.     }
  924.  
  925.     if (ea.cmdidx == CMD_read)
  926.     {
  927.     if (ea.forceit)
  928.     {
  929.         ea.usefilter = TRUE;        /* :r! filter if ea.forceit */
  930.         ea.forceit = FALSE;
  931.     }
  932.     else if (*ea.arg == '!')        /* :r !filter */
  933.     {
  934.         ++ea.arg;
  935.         ea.usefilter = TRUE;
  936.     }
  937.     }
  938.  
  939.     if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift)
  940.     {
  941.     ea.amount = 1;
  942.     while (*ea.arg == *ea.cmd)        /* count number of '>' or '<' */
  943.     {
  944.         ++ea.arg;
  945.         ++ea.amount;
  946.     }
  947.     ea.arg = skipwhite(ea.arg);
  948.     }
  949.  
  950.     /*
  951.      * Check for "+command" argument, before checking for next command.
  952.      * Don't do this for ":read !cmd" and ":write !cmd".
  953.      */
  954.     if ((argt & EDITCMD) && !ea.usefilter)
  955.     ea.do_ecmd_cmd = getargcmd(&ea.arg);
  956.  
  957.     /*
  958.      * Check for '|' to separate commands and '"' to start comments.
  959.      * Don't do this for ":read !cmd" and ":write !cmd".
  960.      */
  961.     if ((argt & TRLBAR) && !ea.usefilter)
  962.     {
  963.     for (p = ea.arg; *p; ++p)
  964.     {
  965.         if (*p == Ctrl('V'))
  966.         {
  967.         if (argt & (USECTRLV | XFILE))
  968.             ++p;        /* skip CTRL-V and next char */
  969.         else
  970.             STRCPY(p, p + 1);    /* remove CTRL-V and skip next char */
  971.         if (*p == NUL)        /* stop at NUL after CTRL-V */
  972.             break;
  973.         }
  974.         else if ((*p == '"' && !(argt & NOTRLCOM)) ||
  975.                               *p == '|' || *p == '\n')
  976.         {
  977.         /*
  978.          * We remove the '\' before the '|', unless USECTRLV is used
  979.          * AND 'b' is present in 'cpoptions'.
  980.          */
  981.         if ((vim_strchr(p_cpo, CPO_BAR) == NULL ||
  982.                        !(argt & USECTRLV)) && *(p - 1) == '\\')
  983.         {
  984.             STRCPY(p - 1, p);    /* remove the backslash */
  985.             --p;
  986.         }
  987.         else
  988.         {
  989.             ea.nextcmd = check_nextcmd(p);
  990.             *p = NUL;
  991.             break;
  992.         }
  993.         }
  994.     }
  995.     if (!(argt & NOTRLCOM))        /* remove trailing spaces */
  996.         del_trailing_spaces(ea.arg);
  997.     }
  998.  
  999.     /*
  1000.      * Check for <newline> to end a shell command.
  1001.      * Also do this for ":read !cmd" and ":write !cmd".
  1002.      */
  1003.     else if (ea.cmdidx == CMD_bang || ea.usefilter)
  1004.     {
  1005.     for (p = ea.arg; *p; ++p)
  1006.     {
  1007.         if (*p == '\\' && p[1])
  1008.         ++p;
  1009.         else if (*p == '\n')
  1010.         {
  1011.         ea.nextcmd = p + 1;
  1012.         *p = NUL;
  1013.         break;
  1014.         }
  1015.     }
  1016.     }
  1017.  
  1018.     if ((argt & DFLALL) && ea.addr_count == 0)
  1019.     {
  1020.     ea.line1 = 1;
  1021.     ea.line2 = curbuf->b_ml.ml_line_count;
  1022.     }
  1023.  
  1024.     /* accept numbered register only when no count allowed (:put) */
  1025.     if (       (argt & REGSTR)
  1026.         && *ea.arg != NUL
  1027.         && valid_yank_reg(*ea.arg, ea.cmdidx != CMD_put)
  1028.         && !((argt & COUNT) && isdigit(*ea.arg)))
  1029.     {
  1030.     ea.regname = *ea.arg++;
  1031. #ifdef WANT_EVAL
  1032.     /* for '=' register: accept the rest of the line as an expression */
  1033.     if (ea.arg[-1] == '=' && ea.arg[0] != NUL)
  1034.     {
  1035.         set_expr_line(vim_strsave(ea.arg));
  1036.         ea.arg += STRLEN(ea.arg);
  1037.     }
  1038. #endif
  1039.     ea.arg = skipwhite(ea.arg);
  1040.     }
  1041.  
  1042.     if ((argt & COUNT) && isdigit(*ea.arg))
  1043.     {
  1044.     n = getdigits(&ea.arg);
  1045.     ea.arg = skipwhite(ea.arg);
  1046.     if (n <= 0)
  1047.     {
  1048.         errormsg = e_zerocount;
  1049.         goto doend;
  1050.     }
  1051.     if (argt & NOTADR)    /* e.g. :buffer 2, :sleep 3 */
  1052.     {
  1053.         ea.line2 = n;
  1054.         if (ea.addr_count == 0)
  1055.         ea.addr_count = 1;
  1056.     }
  1057.     else
  1058.     {
  1059.         ea.line1 = ea.line2;
  1060.         ea.line2 += n - 1;
  1061.         ++ea.addr_count;
  1062.         /*
  1063.          * Be vi compatible: no error message for out of range.
  1064.          */
  1065.         if (ea.line2 > curbuf->b_ml.ml_line_count)
  1066.         ea.line2 = curbuf->b_ml.ml_line_count;
  1067.     }
  1068.     }
  1069.                         /* no arguments allowed */
  1070.     if (!(argt & EXTRA) && *ea.arg != NUL &&
  1071.                  vim_strchr((char_u *)"|\"", *ea.arg) == NULL)
  1072.     {
  1073.     errormsg = e_trailing;
  1074.     goto doend;
  1075.     }
  1076.  
  1077.     if ((argt & NEEDARG) && *ea.arg == NUL)
  1078.     {
  1079.     errormsg = e_argreq;
  1080.     goto doend;
  1081.     }
  1082.  
  1083.     if (argt & XFILE)
  1084.     {
  1085.     int        has_wildcards;    /* need to expand wildcards */
  1086.     char_u        *repl;
  1087.     int        srclen;
  1088.  
  1089.     /*
  1090.      * Decide to expand wildcards *before* replacing '%', '#', etc.  If
  1091.      * the file name contains a wildcard it should not cause expanding.
  1092.      * (it will be expanded anyway if there is a wildcard before replacing).
  1093.      */
  1094.     has_wildcards = mch_has_wildcard(ea.arg);
  1095.     for (p = ea.arg; *p; )
  1096.     {
  1097.         /*
  1098.          * Quick check if this cannot be the start of a special string.
  1099.          */
  1100.         if (vim_strchr((char_u *)"%#<", *p) == NULL)
  1101.         {
  1102.         ++p;
  1103.         continue;
  1104.         }
  1105.  
  1106.         /*
  1107.          * Try to find a match at this position.
  1108.          */
  1109.         repl = eval_vars(p, &srclen, &(ea.do_ecmd_lnum), &errormsg);
  1110.         if (errormsg != NULL)   /* error detected */
  1111.         goto doend;
  1112.         if (repl == NULL)        /* no match found */
  1113.         {
  1114.         p += srclen;
  1115.         continue;
  1116.         }
  1117.  
  1118.         /*
  1119.          * The new command line is build in new_cmdline[].
  1120.          * First allocate it.
  1121.          */
  1122.         len = STRLEN(repl);
  1123.         i = STRLEN(*cmdlinep) + len + 3;
  1124.         if (ea.nextcmd)
  1125.         i += STRLEN(ea.nextcmd);   /* add space for next command */
  1126.         if ((new_cmdline = alloc(i)) == NULL)
  1127.         {
  1128.         vim_free(repl);
  1129.         goto doend;            /* out of memory! */
  1130.         }
  1131.  
  1132.         /*
  1133.          * Copy the stuff before the expanded part.
  1134.          * Copy the expanded stuff.
  1135.          * Copy what came after the expanded part.
  1136.          * Copy the next commands, if there are any.
  1137.          */
  1138.         i = p - *cmdlinep;            /* length of part before match */
  1139.         vim_memmove(new_cmdline, *cmdlinep, (size_t)i);
  1140.         vim_memmove(new_cmdline + i, repl, (size_t)len);
  1141.         vim_free(repl);
  1142.         i += len;                /* remember the end of the string */
  1143.         STRCPY(new_cmdline + i, p + srclen);
  1144.         p = new_cmdline + i;        /* remember where to continue */
  1145.  
  1146.         if (ea.nextcmd)            /* append next command */
  1147.         {
  1148.         i = STRLEN(new_cmdline) + 1;
  1149.         STRCPY(new_cmdline + i, ea.nextcmd);
  1150.         ea.nextcmd = new_cmdline + i;
  1151.         }
  1152.         ea.cmd = new_cmdline + (ea.cmd - *cmdlinep);
  1153.         ea.arg = new_cmdline + (ea.arg - *cmdlinep);
  1154.         if (ea.do_ecmd_cmd != NULL)
  1155.         ea.do_ecmd_cmd = new_cmdline + (ea.do_ecmd_cmd - *cmdlinep);
  1156.         vim_free(*cmdlinep);
  1157.         *cmdlinep = new_cmdline;
  1158.     }
  1159.  
  1160.     /*
  1161.      * One file argument: Expand wildcards.
  1162.      * Don't do this with ":r !command" or ":w !command".
  1163.      */
  1164.     if ((argt & NOSPC) && !ea.usefilter)
  1165.     {
  1166.         /*
  1167.          * May do this twice:
  1168.          * 1. Replace environment variables.
  1169.          * 2. Replace any other wildcards, remove backslashes.
  1170.          */
  1171.         for (n = 1; n <= 2; ++n)
  1172.         {
  1173.         if (n == 2)
  1174.         {
  1175. #if defined(UNIX)
  1176.             /*
  1177.              * Only for Unix we check for more than one file name.
  1178.              * For other systems spaces are considered to be part
  1179.              * of the file name.
  1180.              * Only check here if there is no wildcard, otherwise
  1181.              * ExpandOne will check for errors. This allows
  1182.              * ":e `ls ve*.c`" on Unix.
  1183.              */
  1184.             if (!has_wildcards)
  1185.             for (p = ea.arg; *p; ++p)
  1186.             {
  1187.                 /* skip escaped characters */
  1188.                 if (p[1] && (*p == '\\' || *p == Ctrl('V')))
  1189.                 ++p;
  1190.                 else if (vim_iswhite(*p))
  1191.                 {
  1192.                 errormsg = (char_u *)
  1193.                          "Only one file name allowed";
  1194.                 goto doend;
  1195.                 }
  1196.             }
  1197. #endif
  1198.             /*
  1199.              * halve the number of backslashes (this is Vi compatible)
  1200.              */
  1201.             backslash_halve(ea.arg, has_wildcards);
  1202. #ifdef macintosh
  1203.             /*
  1204.              * translate unix-like path components
  1205.              */
  1206.             slash_n_colon_adjust (ea.arg);
  1207. #endif
  1208.         }
  1209.  
  1210.         if (has_wildcards)
  1211.         {
  1212.             if (n == 1)
  1213.             {
  1214.             /*
  1215.              * First loop: May expand environment variables.  This
  1216.              * can be done much faster with expand_env() than with
  1217.              * something else (e.g., calling a shell).
  1218.              * After expanding environment variables, check again
  1219.              * if there are still wildcards present.
  1220.              */
  1221.             if (vim_strchr(ea.arg, '$') || vim_strchr(ea.arg, '~'))
  1222.             {
  1223.                 expand_env(ea.arg, NameBuff, MAXPATHL);
  1224.                 has_wildcards = mch_has_wildcard(NameBuff);
  1225.                 p = NameBuff;
  1226.             }
  1227.             else
  1228.                 p = NULL;
  1229.             }
  1230.             else /* n == 2 */
  1231.             {
  1232.             if ((p = ExpandOne(ea.arg, NULL, WILD_LIST_NOTFOUND,
  1233.                            WILD_EXPAND_FREE)) == NULL)
  1234.                 goto doend;
  1235.             }
  1236.             if (p != NULL)
  1237.             {
  1238.             /*
  1239.              * The tricky bit here is to replace the argument,
  1240.              * while keeping the "ea.cmd" and "ea.nextcmd" the
  1241.              * pointers correct.
  1242.              */
  1243.             len = ea.arg - *cmdlinep;
  1244.             i = STRLEN(p) + len;
  1245.             if (ea.nextcmd)
  1246.                 i += STRLEN(ea.nextcmd);
  1247.             if ((new_cmdline = alloc((unsigned)i + 2)) != NULL)
  1248.             {
  1249.                 STRNCPY(new_cmdline, *cmdlinep, len);
  1250.                 STRCPY(new_cmdline + len, p);
  1251.                 if (ea.nextcmd)        /* append next command */
  1252.                 {
  1253.                 i = STRLEN(new_cmdline) + 1;
  1254.                 STRCPY(new_cmdline + i, ea.nextcmd);
  1255.                 ea.nextcmd = new_cmdline + i;
  1256.                 }
  1257.                 ea.cmd = new_cmdline + (ea.cmd - *cmdlinep);
  1258.                 ea.arg = new_cmdline + len;
  1259.                 vim_free(*cmdlinep);
  1260.                 *cmdlinep = new_cmdline;
  1261.             }
  1262.             if (n == 2)    /* p came from ExpandOne() */
  1263.                 vim_free(p);
  1264.             }
  1265.         }
  1266.         }
  1267.     }
  1268.     }
  1269.  
  1270. #ifdef WANT_EVAL
  1271.     /*
  1272.      * Skip the command when it's not going to be executed.
  1273.      * The commands like :if, :endif, etc. always need to be executed.
  1274.      * Also make an exception for commands that handle a trailing command
  1275.      * themselves.
  1276.      */
  1277.     if (ea.skip)
  1278.     {
  1279.     switch (ea.cmdidx)
  1280.     {
  1281.         /* commands that need evaluation */
  1282.         case CMD_while:
  1283.         case CMD_endwhile:
  1284.         case CMD_if:
  1285.         case CMD_elseif:
  1286.         case CMD_else:
  1287.         case CMD_endif:    break;
  1288.  
  1289.         /* commands that handle '|' themselves */
  1290.         case CMD_djump:
  1291.         case CMD_dlist:
  1292.         case CMD_dsearch:
  1293.         case CMD_dsplit:
  1294.         case CMD_echo:
  1295.         case CMD_echon:
  1296.         case CMD_execute:
  1297.         case CMD_help:
  1298.         case CMD_ijump:
  1299.         case CMD_ilist:
  1300.         case CMD_isearch:
  1301.         case CMD_isplit:
  1302.         case CMD_let:
  1303.         case CMD_substitute:
  1304.         case CMD_syntax:
  1305.         case CMD_and:
  1306.         case CMD_tilde:    break;
  1307.  
  1308.         default:        goto doend;
  1309.     }
  1310.     }
  1311. #endif
  1312.  
  1313.     /*
  1314.      * Accept buffer name.  Cannot be used at the same time with a buffer
  1315.      * number.
  1316.      */
  1317.     if ((argt & BUFNAME) && *ea.arg && ea.addr_count == 0)
  1318.     {
  1319.     /*
  1320.      * :bdelete and :bunload take several arguments, separated by spaces:
  1321.      * find next space (skipping over escaped characters).
  1322.      * The others take one argument: ignore trailing spaces.
  1323.      */
  1324.     if (ea.cmdidx == CMD_bdelete || ea.cmdidx == CMD_bunload)
  1325.         p = skiptowhite_esc(ea.arg);
  1326.     else
  1327.     {
  1328.         p = ea.arg + STRLEN(ea.arg);
  1329.         while (p > ea.arg && vim_iswhite(p[-1]))
  1330.         --p;
  1331.     }
  1332.     ea.line2 = buflist_findpat(ea.arg, p);
  1333.     if (ea.line2 < 0)        /* failed */
  1334.         goto doend;
  1335.     ea.addr_count = 1;
  1336.     ea.arg = skipwhite(p);
  1337.     }
  1338.  
  1339. /*
  1340.  * 6. switch on command name
  1341.  *
  1342.  * The "ea" structure holds the arguments that can be used.
  1343.  */
  1344.     switch (ea.cmdidx)
  1345.     {
  1346.     case CMD_quit:
  1347.         do_quit(&ea);
  1348.         break;
  1349.  
  1350.     case CMD_qall:
  1351.         do_quit_all(ea.forceit);
  1352.         break;
  1353.  
  1354.     case CMD_close:
  1355.         do_close(&ea);
  1356.         break;
  1357.  
  1358.     case CMD_hide:
  1359.         close_window(curwin, FALSE);    /* don't free buffer */
  1360.         break;
  1361.  
  1362.     case CMD_only:
  1363.         close_others(TRUE, ea.forceit);
  1364.         break;
  1365.  
  1366.     case CMD_stop:
  1367.     case CMD_suspend:
  1368.         do_suspend(ea.forceit);
  1369.         break;
  1370.  
  1371.     case CMD_exit:
  1372.     case CMD_xit:
  1373.     case CMD_wq:
  1374.         do_exit(&ea);
  1375.         break;
  1376.  
  1377.     case CMD_xall:
  1378.     case CMD_wqall:
  1379.         exiting = TRUE;
  1380.         /* FALLTHROUGH */
  1381.  
  1382.     case CMD_wall:
  1383.         do_wqall(&ea);
  1384.         break;
  1385.  
  1386.     case CMD_preserve:
  1387.         ml_preserve(curbuf, TRUE);
  1388.         break;
  1389.  
  1390.     case CMD_recover:
  1391.         do_recover(&ea);
  1392.         break;
  1393.  
  1394.     case CMD_args:
  1395.         do_args(&ea);
  1396.         break;
  1397.  
  1398.     case CMD_wnext:
  1399.     case CMD_wNext:
  1400.     case CMD_wprevious:
  1401.         do_wnext(&ea);
  1402.         break;
  1403.  
  1404.     case CMD_next:
  1405.     case CMD_snext:
  1406.         do_next(&ea);
  1407.         break;
  1408.  
  1409.     case CMD_previous:
  1410.     case CMD_sprevious:
  1411.     case CMD_Next:
  1412.     case CMD_sNext:
  1413.         do_argfile(&ea, curwin->w_arg_idx - (int)ea.line2);
  1414.         break;
  1415.  
  1416.     case CMD_rewind:
  1417.     case CMD_srewind:
  1418.         do_argfile(&ea, 0);
  1419.         break;
  1420.  
  1421.     case CMD_last:
  1422.     case CMD_slast:
  1423.         do_argfile(&ea, arg_file_count - 1);
  1424.         break;
  1425.  
  1426.     case CMD_argument:
  1427.     case CMD_sargument:
  1428.         if (ea.addr_count)
  1429.             i = ea.line2 - 1;
  1430.         else
  1431.             i = curwin->w_arg_idx;
  1432.         do_argfile(&ea, i);
  1433.         break;
  1434.  
  1435.     case CMD_all:
  1436.     case CMD_sall:
  1437.         if (ea.addr_count == 0)
  1438.             ea.line2 = 9999;
  1439.         do_arg_all((int)ea.line2, ea.forceit);
  1440.         break;
  1441.  
  1442.     case CMD_buffer:    /* :[N]buffer [N]    to buffer N */
  1443.     case CMD_sbuffer:    /* :[N]sbuffer [N]    to buffer N */
  1444.         if (*ea.arg)
  1445.             errormsg = e_trailing;
  1446.         else
  1447.         {
  1448.             if (ea.addr_count == 0)    /* default is current buffer */
  1449.             (void)do_buffer(*ea.cmd == 's' ? DOBUF_SPLIT
  1450.                                : DOBUF_GOTO,
  1451.                        DOBUF_CURRENT, FORWARD, 0, ea.forceit);
  1452.             else
  1453.             (void)do_buffer(*ea.cmd == 's' ? DOBUF_SPLIT
  1454.                                : DOBUF_GOTO,
  1455.                  DOBUF_FIRST, FORWARD, (int)ea.line2, ea.forceit);
  1456.         }
  1457.         break;
  1458.  
  1459.     case CMD_bmodified:    /* :[N]bmod [N]        to next mod. buffer */
  1460.     case CMD_sbmodified:    /* :[N]sbmod [N]    to next mod. buffer */
  1461.         (void)do_buffer(*ea.cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
  1462.                    DOBUF_MOD, FORWARD, (int)ea.line2, ea.forceit);
  1463.         break;
  1464.  
  1465.     case CMD_bnext:        /* :[N]bnext [N]    to next buffer */
  1466.     case CMD_sbnext:    /* :[N]sbnext [N]    to next buffer */
  1467.         (void)do_buffer(*ea.cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
  1468.                DOBUF_CURRENT, FORWARD, (int)ea.line2, ea.forceit);
  1469.         break;
  1470.  
  1471.     case CMD_bNext:        /* :[N]bNext [N]    to previous buffer */
  1472.     case CMD_bprevious:    /* :[N]bprevious [N]    to previous buffer */
  1473.     case CMD_sbNext:    /* :[N]sbNext [N]    to previous buffer */
  1474.     case CMD_sbprevious:    /* :[N]sbprevious [N]    to previous buffer */
  1475.         (void)do_buffer(*ea.cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
  1476.               DOBUF_CURRENT, BACKWARD, (int)ea.line2, ea.forceit);
  1477.         break;
  1478.  
  1479.     case CMD_brewind:    /* :brewind        to first buffer */
  1480.     case CMD_sbrewind:    /* :sbrewind        to first buffer */
  1481.         (void)do_buffer(*ea.cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
  1482.                      DOBUF_FIRST, FORWARD, 0, ea.forceit);
  1483.         break;
  1484.  
  1485.     case CMD_blast:        /* :blast        to last buffer */
  1486.     case CMD_sblast:    /* :sblast        to last buffer */
  1487.         (void)do_buffer(*ea.cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
  1488.                       DOBUF_LAST, FORWARD, 0, ea.forceit);
  1489.         break;
  1490.  
  1491.     case CMD_bunload:    /* :[N]bunload[!] [N] [bufname] unload buffer */
  1492.     case CMD_bdelete:    /* :[N]bdelete[!] [N] [bufname] delete buffer */
  1493.         errormsg = do_bufdel(ea.cmdidx == CMD_bdelete ? DOBUF_DEL
  1494.                                   : DOBUF_UNLOAD,
  1495.                      ea.arg, ea.addr_count, (int)ea.line1,
  1496.                            (int)ea.line2, ea.forceit);
  1497.         break;
  1498.  
  1499.     case CMD_unhide:
  1500.     case CMD_sunhide:
  1501.         if (ea.addr_count == 0)
  1502.             ea.line2 = 9999;
  1503.         (void)do_buffer_all((int)ea.line2, FALSE);
  1504.         break;
  1505.  
  1506.     case CMD_ball:
  1507.     case CMD_sball:
  1508.         if (ea.addr_count == 0)
  1509.             ea.line2 = 9999;
  1510.         (void)do_buffer_all((int)ea.line2, TRUE);
  1511.         break;
  1512.  
  1513.     case CMD_buffers:
  1514.     case CMD_files:
  1515.     case CMD_ls:
  1516.         buflist_list();
  1517.         break;
  1518.  
  1519.     case CMD_update:
  1520.         if (curbuf_changed())
  1521.             (void)do_write(&ea);
  1522.         break;
  1523.  
  1524.     case CMD_write:
  1525.         if (ea.usefilter)    /* input lines to shell command */
  1526.             do_bang(1, ea.line1, ea.line2, FALSE, ea.arg, TRUE, FALSE);
  1527.         else
  1528.             (void)do_write(&ea);
  1529.         break;
  1530.  
  1531.     /*
  1532.      * set screen mode
  1533.      * if no argument given, just get the screen size and redraw
  1534.      */
  1535.     case CMD_mode:
  1536.         if (*ea.arg == NUL || mch_screenmode(ea.arg) != FAIL)
  1537.             set_winsize(0, 0, FALSE);
  1538.         break;
  1539.  
  1540.     case CMD_resize:
  1541.         do_resize(&ea);
  1542.         break;
  1543.  
  1544.     case CMD_sview:
  1545.     case CMD_split:
  1546.     case CMD_new:
  1547.         do_splitview(&ea);
  1548.         break;
  1549.  
  1550.     case CMD_edit:
  1551.     case CMD_ex:
  1552.     case CMD_visual:
  1553.     case CMD_view:
  1554.         do_exedit(&ea, NULL);
  1555.         break;
  1556.  
  1557. #ifdef USE_GUI
  1558.     /*
  1559.      * Change from the terminal version to the GUI version.  File names
  1560.      * may be given to redefine the args list -- webb
  1561.      */
  1562.     case CMD_gvim:
  1563.     case CMD_gui:
  1564.         do_gui(&ea);
  1565.         break;
  1566. #endif
  1567.  
  1568.     case CMD_file:
  1569.         do_file(ea.arg, ea.forceit);
  1570.         break;
  1571.  
  1572.     case CMD_swapname:
  1573.         do_swapname();
  1574.         break;
  1575.  
  1576.     case CMD_read:
  1577.         do_read(&ea);
  1578.         break;
  1579.  
  1580.     case CMD_cd:
  1581.     case CMD_chdir:
  1582.         do_cd(&ea);
  1583.         break;
  1584.  
  1585.     case CMD_pwd:
  1586.         do_pwd();
  1587.         break;
  1588.  
  1589.     case CMD_equal:
  1590.         smsg((char_u *)"line %ld", (long)ea.line2);
  1591.         break;
  1592.  
  1593.     case CMD_list:
  1594.         i = curwin->w_p_list;
  1595.         curwin->w_p_list = 1;
  1596.         do_print(&ea);
  1597.         curwin->w_p_list = i;
  1598.         break;
  1599.  
  1600.     case CMD_number:
  1601.     case CMD_pound:            /* :# */
  1602.     case CMD_print:
  1603.         do_print(&ea);
  1604.         break;
  1605.  
  1606.     case CMD_shell:
  1607.         do_shell(NULL, 0);
  1608.         break;
  1609.  
  1610.     case CMD_sleep:
  1611.         do_sleep(&ea);
  1612.         break;
  1613.  
  1614.     case CMD_stag:
  1615.         postponed_split = -1;
  1616.         /*FALLTHROUGH*/
  1617.     case CMD_tag:
  1618.         do_tag(ea.arg, DT_TAG,
  1619.             ea.addr_count ? (int)ea.line2 : 1, ea.forceit);
  1620.         break;
  1621.  
  1622.     case CMD_stselect:
  1623.         postponed_split = -1;
  1624.         /*FALLTHROUGH*/
  1625.     case CMD_tselect:
  1626.         do_tag(ea.arg, DT_SELECT, 0, ea.forceit);
  1627.         break;
  1628.  
  1629.     case CMD_stjump:
  1630.         postponed_split = -1;
  1631.         /*FALLTHROUGH*/
  1632.     case CMD_tjump:
  1633.         do_tag(ea.arg, DT_JUMP, 0, ea.forceit);
  1634.         break;
  1635.  
  1636.     case CMD_pop:        do_ex_tag(&ea, DT_POP); break;
  1637.     case CMD_tnext:        do_ex_tag(&ea, DT_NEXT); break;
  1638.     case CMD_tNext:
  1639.     case CMD_tprevious:    do_ex_tag(&ea, DT_PREV); break;
  1640.     case CMD_trewind:    do_ex_tag(&ea, DT_FIRST); break;
  1641.     case CMD_tlast:        do_ex_tag(&ea, DT_LAST); break;
  1642.  
  1643.     case CMD_tags:
  1644.         do_tags();
  1645.         break;
  1646.  
  1647.     case CMD_marks:
  1648.         do_marks(ea.arg);
  1649.         break;
  1650.  
  1651.     case CMD_jumps:
  1652.         do_jumps();
  1653.         break;
  1654.  
  1655.     case CMD_ascii:
  1656.         do_ascii();
  1657.         break;
  1658.  
  1659. #ifdef FIND_IN_PATH
  1660.     case CMD_checkpath:
  1661.         find_pattern_in_path(NULL, 0, 0, FALSE, FALSE, CHECK_PATH, 1L,
  1662.                    ea.forceit ? ACTION_SHOW_ALL : ACTION_SHOW,
  1663.                           (linenr_t)1, (linenr_t)MAXLNUM);
  1664.         break;
  1665. #endif
  1666.  
  1667.     case CMD_digraphs:
  1668. #ifdef DIGRAPHS
  1669.         if (*ea.arg)
  1670.             putdigraph(ea.arg);
  1671.         else
  1672.             listdigraphs();
  1673. #else
  1674.         EMSG("No digraphs in this version");
  1675. #endif
  1676.         break;
  1677.  
  1678.     case CMD_set:
  1679.         (void)do_set(ea.arg);
  1680.         break;
  1681.  
  1682.     case CMD_fixdel:
  1683.         do_fixdel();
  1684.         break;
  1685.  
  1686. #ifdef AUTOCMD
  1687.     case CMD_augroup:
  1688.     case CMD_autocmd:
  1689.         /*
  1690.          * Disallow auto commands from .exrc and .vimrc in current
  1691.          * directory for security reasons.
  1692.          */
  1693.         if (secure)
  1694.         {
  1695.             secure = 2;
  1696.             errormsg = e_curdir;
  1697.         }
  1698.         else if (ea.cmdidx == CMD_autocmd)
  1699.             do_autocmd(ea.arg, ea.forceit);
  1700.         else
  1701.             do_augroup(ea.arg);
  1702.         break;
  1703.  
  1704.     /*
  1705.      * Apply the automatic commands to all loaded buffers.
  1706.      */
  1707.     case CMD_doautoall:
  1708.         do_autoall(ea.arg);
  1709.         break;
  1710.  
  1711.     /*
  1712.      * Apply the automatic commands to the current buffer.
  1713.      */
  1714.     case CMD_doautocmd:
  1715.         (void)do_doautocmd(ea.arg, TRUE);
  1716.         do_modelines();
  1717.         break;
  1718. #endif
  1719.  
  1720.     case CMD_abbreviate:
  1721.     case CMD_noreabbrev:
  1722.     case CMD_unabbreviate:
  1723.     case CMD_cabbrev:
  1724.     case CMD_cnoreabbrev:
  1725.     case CMD_cunabbrev:
  1726.     case CMD_iabbrev:
  1727.     case CMD_inoreabbrev:
  1728.     case CMD_iunabbrev:
  1729.         do_exmap(&ea, TRUE);        /* almost the same as mapping */
  1730.         break;
  1731.  
  1732.     case CMD_map:
  1733.     case CMD_nmap:
  1734.     case CMD_vmap:
  1735.     case CMD_omap:
  1736.     case CMD_cmap:
  1737.     case CMD_imap:
  1738.     case CMD_noremap:
  1739.     case CMD_nnoremap:
  1740.     case CMD_vnoremap:
  1741.     case CMD_onoremap:
  1742.     case CMD_cnoremap:
  1743.     case CMD_inoremap:
  1744.         /*
  1745.          * If we are sourcing .exrc or .vimrc in current directory we
  1746.          * print the mappings for security reasons.
  1747.          */
  1748.         if (secure)
  1749.         {
  1750.             secure = 2;
  1751.             msg_outtrans(ea.cmd);
  1752.             msg_putchar('\n');
  1753.         }
  1754.     case CMD_unmap:
  1755.     case CMD_nunmap:
  1756.     case CMD_vunmap:
  1757.     case CMD_ounmap:
  1758.     case CMD_cunmap:
  1759.     case CMD_iunmap:
  1760.         do_exmap(&ea, FALSE);
  1761.         break;
  1762.  
  1763.     case CMD_mapclear:
  1764.     case CMD_nmapclear:
  1765.     case CMD_vmapclear:
  1766.     case CMD_omapclear:
  1767.     case CMD_cmapclear:
  1768.     case CMD_imapclear:
  1769.         map_clear(ea.cmd, ea.forceit, FALSE);
  1770.         break;
  1771.  
  1772.     case CMD_abclear:
  1773.     case CMD_iabclear:
  1774.     case CMD_cabclear:
  1775.         map_clear(ea.cmd, TRUE, TRUE);
  1776.         break;
  1777.  
  1778. #ifdef USE_GUI
  1779.     case CMD_menu:        case CMD_noremenu:        case CMD_unmenu:
  1780.     case CMD_amenu:        case CMD_anoremenu:        case CMD_aunmenu:
  1781.     case CMD_nmenu:        case CMD_nnoremenu:        case CMD_nunmenu:
  1782.     case CMD_vmenu:        case CMD_vnoremenu:        case CMD_vunmenu:
  1783.     case CMD_omenu:        case CMD_onoremenu:        case CMD_ounmenu:
  1784.     case CMD_imenu:        case CMD_inoremenu:        case CMD_iunmenu:
  1785.     case CMD_cmenu:        case CMD_cnoremenu:        case CMD_cunmenu:
  1786.         gui_do_menu(&ea);
  1787.         break;
  1788. #endif
  1789.  
  1790.     case CMD_display:
  1791.     case CMD_registers:
  1792.         do_dis(ea.arg);
  1793.         break;
  1794.  
  1795.     case CMD_help:
  1796.         do_help(&ea);
  1797.         break;
  1798.  
  1799.     case CMD_version:
  1800.         do_version(ea.arg);
  1801.         break;
  1802.  
  1803.     case CMD_winsize:
  1804.         do_winsize(ea.arg);
  1805.         break;
  1806.  
  1807.     case CMD_delete:
  1808.     case CMD_yank:
  1809.     case CMD_rshift:
  1810.     case CMD_lshift:
  1811.         do_exops(&ea);
  1812.         break;
  1813.  
  1814.     case CMD_put:
  1815.         /* ":0put" works like ":1put!". */
  1816.         if (ea.line2 == 0)
  1817.         {
  1818.             ea.line2 = 1;
  1819.             ea.forceit = TRUE;
  1820.         }
  1821.         curwin->w_cursor.lnum = ea.line2;
  1822.         do_put(ea.regname, ea.forceit ? BACKWARD : FORWARD, -1L, FALSE);
  1823.         break;
  1824.  
  1825.     case CMD_t:
  1826.     case CMD_copy:
  1827.     case CMD_move:
  1828.         do_copymove(&ea);
  1829.         break;
  1830.  
  1831.     case CMD_coffee:
  1832.         MSG("Insert the beans please.");
  1833.         break;
  1834.  
  1835.     case CMD_and:        /* :& */
  1836.     case CMD_tilde:        /* :~ */
  1837.     case CMD_substitute:    /* :s */
  1838.         do_sub(&ea);
  1839.         break;
  1840.  
  1841.     case CMD_join:
  1842.         do_exjoin(&ea);
  1843.         break;
  1844.  
  1845.     case CMD_global:
  1846.         if (ea.forceit)
  1847.             *ea.cmd = 'v';
  1848.     case CMD_vglobal:
  1849.         do_glob(&ea);
  1850.         break;
  1851.  
  1852.     case CMD_at:            /* :[addr]@r */
  1853.         do_exat(&ea);
  1854.         break;
  1855.  
  1856.     case CMD_bang:
  1857.         do_bang(ea.addr_count, ea.line1, ea.line2,
  1858.                           ea.forceit, ea.arg, TRUE, TRUE);
  1859.         break;
  1860.  
  1861.     case CMD_undo:
  1862.         u_undo(1);
  1863.         break;
  1864.  
  1865.     case CMD_redo:
  1866.         u_redo(1);
  1867.         break;
  1868.  
  1869.     case CMD_source:
  1870.         if (ea.forceit)            /* :so! read vi commands */
  1871.             (void)openscript(ea.arg);
  1872.                         /* :so read ex commands */
  1873.         else if (do_source(ea.arg, FALSE, FALSE) == FAIL)
  1874.             emsg2(e_notopen, ea.arg);
  1875.         break;
  1876.  
  1877. #ifdef VIMINFO
  1878.     case CMD_rviminfo:
  1879.         p = p_viminfo;
  1880.         if (*p_viminfo == NUL)
  1881.             p_viminfo = (char_u *)"'100";
  1882.         if (read_viminfo(ea.arg, TRUE, TRUE, ea.forceit) == FAIL)
  1883.             EMSG("Cannot open viminfo file for reading");
  1884.         p_viminfo = p;
  1885.         break;
  1886.  
  1887.     case CMD_wviminfo:
  1888.         p = p_viminfo;
  1889.         if (*p_viminfo == NUL)
  1890.             p_viminfo = (char_u *)"'100";
  1891.         write_viminfo(ea.arg, ea.forceit);
  1892.         p_viminfo = p;
  1893.         break;
  1894. #endif /* VIMINFO */
  1895.  
  1896.     case CMD_redir:
  1897.         do_redir(&ea);
  1898.         break;
  1899.  
  1900.     case CMD_mkvimrc:
  1901.         if (*ea.arg == NUL)
  1902.             ea.arg = (char_u *)VIMRC_FILE;
  1903.         /*FALLTHROUGH*/
  1904.  
  1905.     case CMD_mkexrc:
  1906.         do_mkrc(&ea);
  1907.         break;
  1908.  
  1909. #ifdef QUICKFIX
  1910.     case CMD_cc:
  1911.         qf_jump(0, ea.addr_count ? (int)ea.line2 : 0, ea.forceit);
  1912.         break;
  1913.  
  1914.     case CMD_cfile:
  1915.         do_cfile(&ea);
  1916.         break;
  1917.  
  1918.     case CMD_clist:
  1919.         qf_list(ea.forceit);
  1920.         break;
  1921.  
  1922.     case CMD_crewind:
  1923.         qf_jump(0, ea.addr_count ? (int)ea.line2 : 1, ea.forceit);
  1924.         break;
  1925.  
  1926.     case CMD_clast:
  1927.         qf_jump(0, ea.addr_count ? (int)ea.line2 : 32767, ea.forceit);
  1928.         break;
  1929.  
  1930.     case CMD_cnext:
  1931.         qf_jump(FORWARD, ea.addr_count ? (int)ea.line2 : 1, ea.forceit);
  1932.         break;
  1933.  
  1934.     case CMD_cNext:
  1935.     case CMD_cprevious:
  1936.         qf_jump(BACKWARD, ea.addr_count ? (int)ea.line2 : 1,
  1937.                                   ea.forceit);
  1938.         break;
  1939. #endif
  1940.  
  1941.     case CMD_cquit:
  1942.         getout(1);    /* this does not always pass on the exit
  1943.                    code to the Manx compiler. why? */
  1944.  
  1945.     case CMD_mark:
  1946.     case CMD_k:
  1947.         do_setmark(&ea);
  1948.         break;
  1949.  
  1950. #ifdef EX_EXTRA
  1951.     case CMD_center:
  1952.     case CMD_right:
  1953.     case CMD_left:
  1954.         do_align(&ea);
  1955.         break;
  1956.  
  1957.     case CMD_retab:
  1958.         do_retab(&ea);
  1959.         break;
  1960.  
  1961.     case CMD_normal:
  1962.         do_normal(&ea);
  1963.         break;
  1964. #endif
  1965.  
  1966. #ifdef QUICKFIX
  1967.     case CMD_make:
  1968.         do_make(ea.arg);
  1969.         break;
  1970. #endif
  1971.  
  1972. #ifdef FIND_IN_PATH
  1973.     case CMD_isearch:
  1974.     case CMD_dsearch:
  1975.         errormsg = do_findpat(&ea, ACTION_SHOW);
  1976.         break;
  1977.  
  1978.     case CMD_ilist:
  1979.     case CMD_dlist:
  1980.         errormsg = do_findpat(&ea, ACTION_SHOW_ALL);
  1981.         break;
  1982.  
  1983.     case CMD_ijump:
  1984.     case CMD_djump:
  1985.         errormsg = do_findpat(&ea, ACTION_GOTO);
  1986.         break;
  1987.  
  1988.     case CMD_isplit:
  1989.     case CMD_dsplit:
  1990.         errormsg = do_findpat(&ea, ACTION_SPLIT);
  1991.         break;
  1992. #endif
  1993.  
  1994. #ifdef SYNTAX_HL
  1995.     case CMD_syntax:
  1996.         do_syntax(&ea);
  1997.         break;
  1998. #endif
  1999.  
  2000.     case CMD_highlight:
  2001.         do_highlight(ea.arg, ea.forceit, FALSE);
  2002.         break;
  2003.  
  2004. #ifdef WANT_EVAL
  2005.     case CMD_echo:
  2006.     case CMD_echon:
  2007.         do_echo(&ea, ea.cmdidx == CMD_echo);
  2008.         break;
  2009.  
  2010.     case CMD_echohl:
  2011.         do_echohl(ea.arg);
  2012.         break;
  2013.  
  2014.     case CMD_execute:
  2015.         do_execute(&ea, getline, cookie);
  2016.         break;
  2017.  
  2018.     case CMD_if:
  2019.         errormsg = do_if(&ea, cstack);
  2020.         break;
  2021.  
  2022.     case CMD_elseif:
  2023.     case CMD_else:
  2024.         errormsg = do_else(&ea, cstack);
  2025.         break;
  2026.  
  2027.     case CMD_endif:
  2028.         if (cstack->cs_idx < 0
  2029.             || (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE))
  2030.             errormsg = (char_u *)":endif without :if";
  2031.         else
  2032.             --cstack->cs_idx;
  2033.         break;
  2034.  
  2035.     case CMD_while:
  2036.         errormsg = do_while(&ea, cstack);
  2037.         break;
  2038.  
  2039.     case CMD_continue:
  2040.         errormsg = do_continue(cstack);
  2041.         break;
  2042.  
  2043.     case CMD_break:
  2044.         errormsg = do_break(cstack);
  2045.         break;
  2046.  
  2047.     case CMD_endwhile:
  2048.         errormsg = do_endwhile(cstack);
  2049.         break;
  2050.  
  2051.     case CMD_let:
  2052.         do_let(&ea);
  2053.         break;
  2054.  
  2055.     case CMD_unlet:
  2056.         do_unlet(ea.arg);
  2057.         break;
  2058. #endif /* WANT_EVAL */
  2059.  
  2060.     case CMD_insert:
  2061.         do_append(ea.line2 - 1, getline, cookie);
  2062.         ex_no_reprint = TRUE;
  2063.         break;
  2064.  
  2065.     case CMD_append:
  2066.         do_append(ea.line2, getline, cookie);
  2067.         ex_no_reprint = TRUE;
  2068.         break;
  2069.  
  2070.     case CMD_change:
  2071.         do_change(ea.line1, ea.line2, getline, cookie);
  2072.         ex_no_reprint = TRUE;
  2073.         break;
  2074.  
  2075.     case CMD_z:
  2076.         do_z(ea.line2, ea.arg);
  2077.         ex_no_reprint = TRUE;
  2078.         break;
  2079.  
  2080.     case CMD_intro:
  2081.         do_intro();
  2082.         break;
  2083.  
  2084. #ifdef HAVE_PERL_INTERP
  2085.     case CMD_perl:
  2086.         do_perl(&ea);
  2087.         break;
  2088.  
  2089.     case CMD_perldo:
  2090.         do_perldo(&ea);
  2091.         break;
  2092. #endif
  2093.  
  2094. #ifdef HAVE_PYTHON
  2095.     case CMD_python:
  2096.         do_python(&ea);
  2097.         break;
  2098.  
  2099.     case CMD_pyfile:
  2100.         do_pyfile(&ea);
  2101.         break;
  2102. #endif
  2103.  
  2104. #ifdef USE_SNIFF
  2105.     case CMD_sniff:
  2106.         do_sniff(ea.arg);
  2107.         break;
  2108. #endif
  2109.  
  2110.     default:
  2111.         /* Illegal commands have already been handled */
  2112.         errormsg = (char_u *)"Sorry, this command is not implemented";
  2113.     }
  2114.  
  2115.  
  2116. doend:
  2117.     if (curwin->w_cursor.lnum == 0)    /* can happen with zero line number */
  2118.     curwin->w_cursor.lnum = 1;
  2119.  
  2120.     if (errormsg != NULL && *errormsg != NUL && !did_emsg)
  2121.     {
  2122.     emsg(errormsg);
  2123.     if (sourcing)
  2124.     {
  2125.         MSG_PUTS(": ");
  2126.         msg_outtrans(*cmdlinep);
  2127.     }
  2128.     }
  2129.     if (ea.nextcmd && *ea.nextcmd == NUL)    /* not really a next command */
  2130.     ea.nextcmd = NULL;
  2131.     return ea.nextcmd;
  2132. }
  2133.  
  2134. /*
  2135.  * This is all pretty much copied from do_one_cmd(), with all the extra stuff
  2136.  * we don't need/want deleted.    Maybe this could be done better if we didn't
  2137.  * repeat all this stuff.  The only problem is that they may not stay perfectly
  2138.  * compatible with each other, but then the command line syntax probably won't
  2139.  * change that much -- webb.
  2140.  */
  2141.     char_u *
  2142. set_one_cmd_context(buff)
  2143.     char_u    *buff;        /* buffer for command string */
  2144. {
  2145.     char_u        *p;
  2146.     char_u        *cmd, *arg;
  2147.     int            i;
  2148.     CMDIDX        cmdidx;
  2149.     long        argt;
  2150.     char_u        delim;
  2151.     int            forceit = FALSE;
  2152.     int            usefilter = FALSE;  /* filter instead of file name */
  2153.  
  2154.     expand_pattern = buff;
  2155.     expand_context = EXPAND_COMMANDS;    /* Default until we get past command */
  2156.     expand_set_path = FALSE;
  2157.  
  2158. /*
  2159.  * 2. skip comment lines and leading space, colons or bars
  2160.  */
  2161.     for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++)
  2162.     ;
  2163.     expand_pattern = cmd;
  2164.  
  2165.     if (*cmd == NUL)
  2166.     return NULL;
  2167.     if (*cmd == '"')        /* ignore comment lines */
  2168.     {
  2169.     expand_context = EXPAND_NOTHING;
  2170.     return NULL;
  2171.     }
  2172.  
  2173. /*
  2174.  * 3. parse a range specifier of the form: addr [,addr] [;addr] ..
  2175.  */
  2176.     /*
  2177.      * Backslashed delimiters after / or ? will be skipped, and commands will
  2178.      * not be expanded between /'s and ?'s or after "'". -- webb
  2179.      */
  2180.     while (*cmd != NUL && (vim_isspace(*cmd) || isdigit(*cmd) ||
  2181.                 vim_strchr((char_u *)".$%*'/?-+,;", *cmd) != NULL))
  2182.     {
  2183.     if (*cmd == '\'')
  2184.     {
  2185.         if (*++cmd == NUL)
  2186.         expand_context = EXPAND_NOTHING;
  2187.     }
  2188.     else if (*cmd == '/' || *cmd == '?')
  2189.     {
  2190.         delim = *cmd++;
  2191.         while (*cmd != NUL && *cmd != delim)
  2192.         if (*cmd++ == '\\' && *cmd != NUL)
  2193.             ++cmd;
  2194.         if (*cmd == NUL)
  2195.         expand_context = EXPAND_NOTHING;
  2196.     }
  2197.     if (*cmd != NUL)
  2198.         ++cmd;
  2199.     }
  2200.  
  2201. /*
  2202.  * 4. parse command
  2203.  */
  2204.  
  2205.     cmd = skipwhite(cmd);
  2206.     expand_pattern = cmd;
  2207.     if (*cmd == NUL)
  2208.     return NULL;
  2209.     if (*cmd == '"')
  2210.     {
  2211.     expand_context = EXPAND_NOTHING;
  2212.     return NULL;
  2213.     }
  2214.  
  2215.     if (*cmd == '|' || *cmd == '\n')
  2216.     return cmd + 1;            /* There's another command */
  2217.  
  2218.     /*
  2219.      * Isolate the command and search for it in the command table.
  2220.      * Exeptions:
  2221.      * - the 'k' command can directly be followed by any character.
  2222.      * - the 's' command can be followed directly by 'c', 'g' or 'r'
  2223.      */
  2224.     if (*cmd == 'k')
  2225.     {
  2226.     cmdidx = CMD_k;
  2227.     p = cmd + 1;
  2228.     }
  2229.     else
  2230.     {
  2231.     p = cmd;
  2232.     while (isalpha(*p) || *p == '*')    /* Allow * wild card */
  2233.         ++p;
  2234.         /* check for non-alpha command */
  2235.     if (p == cmd && vim_strchr((char_u *)"@!=><&~#", *p) != NULL)
  2236.         ++p;
  2237.     i = (int)(p - cmd);
  2238.  
  2239.     if (i == 0)
  2240.     {
  2241.         expand_context = EXPAND_UNSUCCESSFUL;
  2242.         return NULL;
  2243.     }
  2244.     for (cmdidx = (CMDIDX)0; cmdidx < CMD_SIZE;
  2245.                        cmdidx = (CMDIDX)((int)cmdidx + 1))
  2246.         if (STRNCMP(cmdnames[cmdidx].cmd_name, cmd, (size_t)i) == 0)
  2247.         break;
  2248.     }
  2249.  
  2250.     /*
  2251.      * If the cursor is touching the command, and it ends in an alphabetic
  2252.      * character, complete the command name.
  2253.      */
  2254.     if (*p == NUL && isalpha(p[-1]))
  2255.     return NULL;
  2256.  
  2257.     if (cmdidx == CMD_SIZE)
  2258.     {
  2259.     if (*cmd == 's' && vim_strchr((char_u *)"cgr", cmd[1]) != NULL)
  2260.     {
  2261.         cmdidx = CMD_substitute;
  2262.         p = cmd + 1;
  2263.     }
  2264.     else
  2265.     {
  2266.         /* Not still touching the command and it was an illegal command */
  2267.         expand_context = EXPAND_UNSUCCESSFUL;
  2268.         return NULL;
  2269.     }
  2270.     }
  2271.  
  2272.     expand_context = EXPAND_NOTHING; /* Default now that we're past command */
  2273.  
  2274.     if (*p == '!')            /* forced commands */
  2275.     {
  2276.     forceit = TRUE;
  2277.     ++p;
  2278.     }
  2279.  
  2280. /*
  2281.  * 5. parse arguments
  2282.  */
  2283.     argt = cmdnames[cmdidx].cmd_argt;
  2284.  
  2285.     arg = skipwhite(p);
  2286.  
  2287.     if (cmdidx == CMD_write || cmdidx == CMD_update)
  2288.     {
  2289.     if (*arg == '>')            /* append */
  2290.     {
  2291.         if (*++arg == '>')
  2292.         ++arg;
  2293.         arg = skipwhite(arg);
  2294.     }
  2295.     else if (*arg == '!' && cmdidx == CMD_write)    /* :w !filter */
  2296.     {
  2297.         ++arg;
  2298.         usefilter = TRUE;
  2299.     }
  2300.     }
  2301.  
  2302.     if (cmdidx == CMD_read)
  2303.     {
  2304.     usefilter = forceit;            /* :r! filter if forced */
  2305.     if (*arg == '!')            /* :r !filter */
  2306.     {
  2307.         ++arg;
  2308.         usefilter = TRUE;
  2309.     }
  2310.     }
  2311.  
  2312.     if (cmdidx == CMD_lshift || cmdidx == CMD_rshift)
  2313.     {
  2314.     while (*arg == *cmd)        /* allow any number of '>' or '<' */
  2315.         ++arg;
  2316.     arg = skipwhite(arg);
  2317.     }
  2318.  
  2319.     /* Does command allow "+command"? */
  2320.     if ((argt & EDITCMD) && !usefilter && *arg == '+')
  2321.     {
  2322.     /* Check if we're in the +command */
  2323.     p = arg + 1;
  2324.     arg = skip_cmd_arg(arg);
  2325.  
  2326.     /* Still touching the command after '+'? */
  2327.     if (*arg == NUL)
  2328.         return p;
  2329.  
  2330.     /* Skip space(s) after +command to get to the real argument */
  2331.     arg = skipwhite(arg);
  2332.     }
  2333.  
  2334.     /*
  2335.      * Check for '|' to separate commands and '"' to start comments.
  2336.      * Don't do this for ":read !cmd" and ":write !cmd".
  2337.      */
  2338.     if ((argt & TRLBAR) && !usefilter)
  2339.     {
  2340.     p = arg;
  2341.     while (*p)
  2342.     {
  2343.         if (*p == Ctrl('V'))
  2344.         {
  2345.         if (p[1] != NUL)
  2346.             ++p;
  2347.         }
  2348.         else if ( (*p == '"' && !(argt & NOTRLCOM))
  2349.             || *p == '|' || *p == '\n')
  2350.         {
  2351.         if (*(p - 1) != '\\')
  2352.         {
  2353.             if (*p == '|' || *p == '\n')
  2354.             return p + 1;
  2355.             return NULL;    /* It's a comment */
  2356.         }
  2357.         }
  2358.         ++p;
  2359.     }
  2360.     }
  2361.  
  2362.                         /* no arguments allowed */
  2363.     if (!(argt & EXTRA) && *arg != NUL &&
  2364.                     vim_strchr((char_u *)"|\"", *arg) == NULL)
  2365.     return NULL;
  2366.  
  2367.     /* Find start of last argument (argument just before cursor): */
  2368.     p = buff + STRLEN(buff);
  2369.     while (p != arg && *p != ' ' && *p != TAB)
  2370.     p--;
  2371.     if (*p == ' ' || *p == TAB)
  2372.     p++;
  2373.     expand_pattern = p;
  2374.  
  2375.     if (argt & XFILE)
  2376.     {
  2377.     int in_quote = FALSE;
  2378.     char_u *bow = NULL;    /* Beginning of word */
  2379.  
  2380.     /*
  2381.      * Allow spaces within back-quotes to count as part of the argument
  2382.      * being expanded.
  2383.      */
  2384.     expand_pattern = skipwhite(arg);
  2385.     for (p = expand_pattern; *p; ++p)
  2386.     {
  2387.         if (*p == '\\' && p[1])
  2388.         ++p;
  2389. #ifdef SPACE_IN_FILENAME
  2390.         else if (vim_iswhite(*p) && (!(argt & NOSPC) || usefilter))
  2391. #else
  2392.         else if (vim_iswhite(*p))
  2393. #endif
  2394.         {
  2395.         p = skipwhite(p);
  2396.         if (in_quote)
  2397.             bow = p;
  2398.         else
  2399.             expand_pattern = p;
  2400.         --p;
  2401.         }
  2402.         else if (*p == '`')
  2403.         {
  2404.         if (!in_quote)
  2405.         {
  2406.             expand_pattern = p;
  2407.             bow = p + 1;
  2408.         }
  2409.         in_quote = !in_quote;
  2410.         }
  2411.     }
  2412.  
  2413.     /*
  2414.      * If we are still inside the quotes, and we passed a space, just
  2415.      * expand from there.
  2416.      */
  2417.     if (bow != NULL && in_quote)
  2418.         expand_pattern = bow;
  2419.     expand_context = EXPAND_FILES;
  2420.     }
  2421.  
  2422. /*
  2423.  * 6. switch on command name
  2424.  */
  2425.     switch (cmdidx)
  2426.     {
  2427.     case CMD_cd:
  2428.     case CMD_chdir:
  2429.         expand_context = EXPAND_DIRECTORIES;
  2430.         break;
  2431.     case CMD_global:
  2432.     case CMD_vglobal:
  2433.         delim = *arg;        /* get the delimiter */
  2434.         if (delim)
  2435.         ++arg;            /* skip delimiter if there is one */
  2436.  
  2437.         while (arg[0] != NUL && arg[0] != delim)
  2438.         {
  2439.         if (arg[0] == '\\' && arg[1] != NUL)
  2440.             ++arg;
  2441.         ++arg;
  2442.         }
  2443.         if (arg[0] != NUL)
  2444.         return arg + 1;
  2445.         break;
  2446.     case CMD_and:
  2447.     case CMD_substitute:
  2448.         delim = *arg;
  2449.         if (delim)
  2450.         ++arg;
  2451.         for (i = 0; i < 2; i++)
  2452.         {
  2453.         while (arg[0] != NUL && arg[0] != delim)
  2454.         {
  2455.             if (arg[0] == '\\' && arg[1] != NUL)
  2456.             ++arg;
  2457.             ++arg;
  2458.         }
  2459.         if (arg[0] != NUL)    /* skip delimiter */
  2460.             ++arg;
  2461.         }
  2462.         while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL)
  2463.         ++arg;
  2464.         if (arg[0] != NUL)
  2465.         return arg;
  2466.         break;
  2467.     case CMD_isearch:
  2468.     case CMD_dsearch:
  2469.     case CMD_ilist:
  2470.     case CMD_dlist:
  2471.     case CMD_ijump:
  2472.     case CMD_djump:
  2473.     case CMD_isplit:
  2474.     case CMD_dsplit:
  2475.         arg = skipwhite(skipdigits(arg));        /* skip count */
  2476.         if (*arg == '/')    /* Match regexp, not just whole words */
  2477.         {
  2478.         for (++arg; *arg && *arg != '/'; arg++)
  2479.             if (*arg == '\\' && arg[1] != NUL)
  2480.             arg++;
  2481.         if (*arg)
  2482.         {
  2483.             arg = skipwhite(arg + 1);
  2484.  
  2485.             /* Check for trailing illegal characters */
  2486.             if (*arg && vim_strchr((char_u *)"|\"\n", *arg) == NULL)
  2487.             expand_context = EXPAND_NOTHING;
  2488.             else
  2489.             return arg;
  2490.         }
  2491.         }
  2492.         break;
  2493. #ifdef AUTOCMD
  2494.     case CMD_autocmd:
  2495.         return set_context_in_autocmd(arg, FALSE);
  2496.  
  2497.     case CMD_doautocmd:
  2498.         return set_context_in_autocmd(arg, TRUE);
  2499. #endif
  2500.     case CMD_set:
  2501.         set_context_in_set_cmd(arg);
  2502.         break;
  2503.     case CMD_stag:
  2504.     case CMD_tag:
  2505.     case CMD_stselect:
  2506.     case CMD_tselect:
  2507.         expand_context = EXPAND_TAGS;
  2508.         expand_pattern = arg;
  2509.         break;
  2510.     case CMD_help:
  2511.         expand_context = EXPAND_HELP;
  2512.         expand_pattern = arg;
  2513.         break;
  2514.     case CMD_augroup:
  2515.         expand_context = EXPAND_AUGROUP;
  2516.         expand_pattern = arg;
  2517.         break;
  2518. #ifdef SYNTAX_HL
  2519.     case CMD_syntax:
  2520.         set_context_in_syntax_cmd(arg);
  2521.         break;
  2522. #endif
  2523. #ifdef WANT_EVAL
  2524.     case CMD_echohl:
  2525.         expand_context = EXPAND_HIGHLIGHT;
  2526.         expand_pattern = arg;
  2527.         break;
  2528. #endif
  2529.     case CMD_highlight:
  2530.         set_context_in_highlight_cmd(arg);
  2531.         break;
  2532.     case CMD_bdelete:
  2533.     case CMD_bunload:
  2534.         while ((expand_pattern = vim_strchr(arg, ' ')) != NULL)
  2535.         arg = expand_pattern + 1;
  2536.     case CMD_buffer:
  2537.     case CMD_sbuffer:
  2538.         expand_context = EXPAND_BUFFERS;
  2539.         expand_pattern = arg;
  2540.         break;
  2541. #ifdef USE_GUI
  2542.     case CMD_menu:        case CMD_noremenu:        case CMD_unmenu:
  2543.     case CMD_amenu:        case CMD_anoremenu:        case CMD_aunmenu:
  2544.     case CMD_nmenu:        case CMD_nnoremenu:        case CMD_nunmenu:
  2545.     case CMD_vmenu:        case CMD_vnoremenu:        case CMD_vunmenu:
  2546.     case CMD_omenu:        case CMD_onoremenu:        case CMD_ounmenu:
  2547.     case CMD_imenu:        case CMD_inoremenu:        case CMD_iunmenu:
  2548.     case CMD_cmenu:        case CMD_cnoremenu:        case CMD_cunmenu:
  2549.         return gui_set_context_in_menu_cmd(cmd, arg, forceit);
  2550. #endif
  2551.     default:
  2552.         break;
  2553.     }
  2554.     return NULL;
  2555. }
  2556.  
  2557. /*
  2558.  * get a single EX address
  2559.  *
  2560.  * Set ptr to the next character after the part that was interpreted.
  2561.  * Set ptr to NULL when an error is encountered.
  2562.  *
  2563.  * Return MAXLNUM when no Ex address was found.
  2564.  */
  2565.     static linenr_t
  2566. get_address(ptr)
  2567.     char_u    **ptr;
  2568. {
  2569.     int        c;
  2570.     int        i;
  2571.     long    n;
  2572.     char_u    *cmd;
  2573.     FPOS    pos;
  2574.     FPOS    *fp;
  2575.     linenr_t    lnum;
  2576.  
  2577.     cmd = skipwhite(*ptr);
  2578.     lnum = MAXLNUM;
  2579.     do
  2580.     {
  2581.     switch (*cmd)
  2582.     {
  2583.         case '.':                /* '.' - Cursor position */
  2584.             ++cmd;
  2585.             lnum = curwin->w_cursor.lnum;
  2586.             break;
  2587.  
  2588.         case '$':                /* '$' - last line */
  2589.             ++cmd;
  2590.             lnum = curbuf->b_ml.ml_line_count;
  2591.             break;
  2592.  
  2593.         case '\'':                /* ''' - mark */
  2594.             if (*++cmd == NUL || (check_mark(
  2595.                     fp = getmark(*cmd++, FALSE)) == FAIL))
  2596.             {
  2597.                 cmd = NULL;
  2598.                 goto error;
  2599.             }
  2600.             lnum = fp->lnum;
  2601.             break;
  2602.  
  2603.         case '/':
  2604.         case '?':                /* '/' or '?' - search */
  2605.             c = *cmd++;
  2606.             pos = curwin->w_cursor;        /* save curwin->w_cursor */
  2607.             /*
  2608.              * When '/' or '?' follows another address, start from
  2609.              * there.
  2610.              */
  2611.             if (lnum != MAXLNUM)
  2612.                 curwin->w_cursor.lnum = lnum;
  2613.             /*
  2614.              * Start a forward search at the end of the line.
  2615.              * Start a backward search at the start of the line.
  2616.              * This makes sure we never match in the current line,
  2617.              * and can match anywhere in the next/previous line.
  2618.              */
  2619.             if (c == '/')
  2620.                 curwin->w_cursor.col = MAXCOL;
  2621.             else
  2622.                 curwin->w_cursor.col = 0;
  2623.             searchcmdlen = 0;
  2624.             if (!do_search(NULL, c, cmd, 1L,
  2625.                       SEARCH_HIS + SEARCH_MSG + SEARCH_START))
  2626.             {
  2627.                 curwin->w_cursor = pos;
  2628.                 cmd = NULL;
  2629.                 goto error;
  2630.             }
  2631.             lnum = curwin->w_cursor.lnum;
  2632.             curwin->w_cursor = pos;
  2633.                         /* adjust command string pointer */
  2634.             cmd += searchcmdlen;
  2635.             break;
  2636.  
  2637.         case '\\':            /* "\?", "\/" or "\&", repeat search */
  2638.             ++cmd;
  2639.             if (*cmd == '&')
  2640.                 i = RE_SUBST;
  2641.             else if (*cmd == '?' || *cmd == '/')
  2642.                 i = RE_SEARCH;
  2643.             else
  2644.             {
  2645.                 emsg(e_backslash);
  2646.                 cmd = NULL;
  2647.                 goto error;
  2648.             }
  2649.  
  2650.             /*
  2651.              * When search follows another address, start from
  2652.              * there.
  2653.              */
  2654.             if (lnum != MAXLNUM)
  2655.                 pos.lnum = lnum;
  2656.             else
  2657.                 pos.lnum = curwin->w_cursor.lnum;
  2658.  
  2659.             /*
  2660.              * Start the search just like for the above do_search().
  2661.              */
  2662.             if (*cmd != '?')
  2663.                 pos.col = MAXCOL;
  2664.             else
  2665.                 pos.col = 0;
  2666.             if (searchit(curbuf, &pos,
  2667.                     *cmd == '?' ? BACKWARD : FORWARD,
  2668.                     (char_u *)"", 1L,
  2669.                     SEARCH_MSG + SEARCH_START, i) == OK)
  2670.                 lnum = pos.lnum;
  2671.             else
  2672.             {
  2673.                 cmd = NULL;
  2674.                 goto error;
  2675.             }
  2676.             ++cmd;
  2677.             break;
  2678.  
  2679.         default:
  2680.             if (isdigit(*cmd))    /* absolute line number */
  2681.                 lnum = getdigits(&cmd);
  2682.     }
  2683.  
  2684.     for (;;)
  2685.     {
  2686.         cmd = skipwhite(cmd);
  2687.         if (*cmd != '-' && *cmd != '+' && !isdigit(*cmd))
  2688.         break;
  2689.  
  2690.         if (lnum == MAXLNUM)
  2691.         lnum = curwin->w_cursor.lnum;    /* "+1" is same as ".+1" */
  2692.         if (isdigit(*cmd))
  2693.         i = '+';        /* "number" is same as "+number" */
  2694.         else
  2695.         i = *cmd++;
  2696.         if (!isdigit(*cmd))        /* '+' is '+1', but '+0' is not '+1' */
  2697.         n = 1;
  2698.         else
  2699.         n = getdigits(&cmd);
  2700.         if (i == '-')
  2701.         lnum -= n;
  2702.         else
  2703.         lnum += n;
  2704.     }
  2705.     } while (*cmd == '/' || *cmd == '?');
  2706.  
  2707. error:
  2708.     *ptr = cmd;
  2709.     return lnum;
  2710. }
  2711.  
  2712. /*
  2713.  * If 'autowrite' option set, try to write the file.
  2714.  *
  2715.  * return FAIL for failure, OK otherwise
  2716.  */
  2717.     int
  2718. autowrite(buf, forceit)
  2719.     BUF        *buf;
  2720.     int        forceit;
  2721. {
  2722.     if (!p_aw || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL)
  2723.     return FAIL;
  2724.     return buf_write_all(buf);
  2725. }
  2726.  
  2727. /*
  2728.  * flush all buffers, except the ones that are readonly
  2729.  */
  2730.     void
  2731. autowrite_all()
  2732. {
  2733.     BUF        *buf;
  2734.  
  2735.     if (!p_aw)
  2736.     return;
  2737.     for (buf = firstbuf; buf; buf = buf->b_next)
  2738.     if (buf_changed(buf) && !buf->b_p_ro)
  2739.     {
  2740.         (void)buf_write_all(buf);
  2741. #ifdef AUTOCMD
  2742.         /* an autocommand may have deleted the buffer */
  2743.         if (!buf_valid(buf))
  2744.         buf = firstbuf;
  2745. #endif
  2746.     }
  2747. }
  2748.  
  2749.     static int
  2750. check_readonly(forceit)
  2751.     int        forceit;
  2752. {
  2753.     if (!forceit && curbuf->b_p_ro)
  2754.     {
  2755.     emsg(e_readonly);
  2756.     return TRUE;
  2757.     }
  2758.     return FALSE;
  2759. }
  2760.  
  2761. /*
  2762.  * return TRUE if buffer was changed and cannot be abandoned.
  2763.  */
  2764.     static int
  2765. check_changed(buf, checkaw, mult_win, forceit)
  2766.     BUF        *buf;
  2767.     int        checkaw;        /* do autowrite if buffer was changed */
  2768.     int        mult_win;        /* check also when several windows for the buffer */
  2769.     int        forceit;
  2770. {
  2771.     if (    !forceit &&
  2772.         buf_changed(buf) && (mult_win || buf->b_nwindows <= 1) &&
  2773.         (!checkaw || autowrite(buf, forceit) == FAIL))
  2774.     {
  2775.     emsg(e_nowrtmsg);
  2776.     return TRUE;
  2777.     }
  2778.     return FALSE;
  2779. }
  2780.  
  2781. /*
  2782.  * Return TRUE if the buffer "buf" can be abandoned, either by making it
  2783.  * hidden, autowriting it or unloading it.
  2784.  */
  2785.     int
  2786. can_abandon(buf, forceit)
  2787.     BUF        *buf;
  2788.     int        forceit;
  2789. {
  2790.     return (       p_hid
  2791.         || !buf_changed(buf)
  2792.         || buf->b_nwindows > 1
  2793.         || autowrite(buf, forceit) == OK
  2794.         || forceit);
  2795. }
  2796.  
  2797. /*
  2798.  * Return TRUE if any buffer was changed and cannot be abandoned.
  2799.  * That changed buffer becomes the current buffer.
  2800.  */
  2801.     int
  2802. check_changed_any()
  2803. {
  2804.     BUF        *buf;
  2805.     int        save;
  2806.  
  2807.     /* check curbuf first: if it was changed we can't abondon it */
  2808.     if (buf_changed(curbuf))
  2809.     buf = curbuf;
  2810.     else
  2811.     {
  2812.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  2813.         if (buf_changed(buf))
  2814.         break;
  2815.     }
  2816.     if (buf == NULL)
  2817.     return FALSE;
  2818.  
  2819.     exiting = FALSE;
  2820.     /* There must be a wait_return for this message, do_buffer()
  2821.      * may cause a redraw.  But wait_return() is a no-op when vgetc()
  2822.      * is busy (Quit used from window menu), then make sure we don't
  2823.      * cause a scroll up. */
  2824.     if (vgetc_busy)
  2825.     {
  2826.     msg_row = cmdline_row;
  2827.     msg_col = 0;
  2828.     msg_didout = FALSE;
  2829.     }
  2830.     if (EMSG2("No write since last change for buffer \"%s\"",
  2831.         buf->b_fname == NULL ? (char_u *)"No File" :
  2832.         buf->b_fname))
  2833.     {
  2834.     save = no_wait_return;
  2835.     no_wait_return = FALSE;
  2836.     wait_return(FALSE);
  2837.     no_wait_return = save;
  2838.     }
  2839.     (void)do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, buf->b_fnum, 0);
  2840.     return TRUE;
  2841. }
  2842.  
  2843. /*
  2844.  * return FAIL if there is no file name, OK if there is one
  2845.  * give error message for FAIL
  2846.  */
  2847.     int
  2848. check_fname()
  2849. {
  2850.     if (curbuf->b_ffname == NULL)
  2851.     {
  2852.     emsg(e_noname);
  2853.     return FAIL;
  2854.     }
  2855.     return OK;
  2856. }
  2857.  
  2858. /*
  2859.  * flush the contents of a buffer, unless it has no file name
  2860.  *
  2861.  * return FAIL for failure, OK otherwise
  2862.  */
  2863.     static int
  2864. buf_write_all(buf)
  2865.     BUF        *buf;
  2866. {
  2867.     int        retval;
  2868. #ifdef AUTOCMD
  2869.     BUF        *old_curbuf = curbuf;
  2870. #endif
  2871.  
  2872.     retval = (buf_write(buf, buf->b_ffname, buf->b_fname,
  2873.                      (linenr_t)1, buf->b_ml.ml_line_count,
  2874.                           FALSE, FALSE, TRUE, FALSE));
  2875. #ifdef AUTOCMD
  2876.     if (curbuf != old_curbuf)
  2877.     MSG("Warning: Entered other buffer unexpectedly (check autocommands)");
  2878. #endif
  2879.     return retval;
  2880. }
  2881.  
  2882. /*
  2883.  * get + command from ex argument
  2884.  */
  2885.     static char_u *
  2886. getargcmd(argp)
  2887.     char_u **argp;
  2888. {
  2889.     char_u *arg = *argp;
  2890.     char_u *command = NULL;
  2891.  
  2892.     if (*arg == '+')        /* +[command] */
  2893.     {
  2894.     ++arg;
  2895.     if (vim_isspace(*arg))
  2896.         command = (char_u *)"$";
  2897.     else
  2898.     {
  2899.         command = arg;
  2900.         arg = skip_cmd_arg(command);
  2901.         if (*arg)
  2902.         *arg++ = NUL;    /* terminate command with NUL */
  2903.     }
  2904.  
  2905.     arg = skipwhite(arg);    /* skip over spaces */
  2906.     *argp = arg;
  2907.     }
  2908.     return command;
  2909. }
  2910.  
  2911. /*
  2912.  * Find end of "+command" argument.  Skip over "\ " and "\\".
  2913.  */
  2914.     static char_u *
  2915. skip_cmd_arg(p)
  2916.     char_u *p;
  2917. {
  2918.     while (*p && !vim_isspace(*p))
  2919.     {
  2920.     if (*p == '\\' && p[1] != NUL)
  2921.         ++p;
  2922.     ++p;
  2923.     }
  2924.     return p;
  2925. }
  2926.  
  2927. /*
  2928.  * Return TRUE if "str" starts with a backslash that should be removed.
  2929.  * For MS-DOS, WIN32 and OS/2 this is only done when the character after the
  2930.  * backslash is not a normal file name character.
  2931.  * Although '$' is a valid file name character, we remove the backslash before
  2932.  * it, to be able to disginguish between a file name that starts with '$' and
  2933.  * the name of an environment variable.
  2934.  * Make sure that "\\mch\file" isn't translated into "\mch\file".
  2935.  */
  2936.     static int
  2937. rem_backslash(str)
  2938.     char_u  *str;
  2939. {
  2940. #ifdef BACKSLASH_IN_FILENAME
  2941.     return (str[0] == '\\'
  2942.         && (str[1] == '$'
  2943.         || (str[1] != NUL
  2944.             && str[1] != '*'
  2945.             && str[1] != '?'
  2946.             && !vim_isfilec(str[1]))));
  2947. #else
  2948.     return (str[0] == '\\' && str[1] != NUL);
  2949. #endif
  2950. }
  2951.  
  2952. /*
  2953.  * Halve the number of backslashes in a file name argument.
  2954.  * For MS-DOS we only do this if the character after the backslash
  2955.  * is not a normal file character.
  2956.  * For Unix, when wildcards are going to be expanded, don't remove
  2957.  * backslashes before special characters.
  2958.  */
  2959.     void
  2960. backslash_halve(p, has_wildcards)
  2961.     char_u  *p;
  2962.     int        has_wildcards;    /* going to expand wildcards later */
  2963. {
  2964.     for ( ; *p; ++p)
  2965.     if (rem_backslash(p)
  2966. #if defined(UNIX) || defined(OS2)
  2967.         && !(has_wildcards &&
  2968.             vim_strchr((char_u *)" *?[{`$\\", p[1]))
  2969. #endif
  2970.                            )
  2971.         STRCPY(p, p + 1);
  2972. }
  2973.  
  2974. /*
  2975.  * write current buffer to file 'eap->arg'
  2976.  * if 'eap->append' is TRUE, append to the file
  2977.  *
  2978.  * if *eap->arg == NUL write to current file
  2979.  * if b_notedited is TRUE, check for overwriting current file
  2980.  *
  2981.  * return FAIL for failure, OK otherwise
  2982.  */
  2983.     static int
  2984. do_write(eap)
  2985.     EXARG    *eap;
  2986. {
  2987.     int        other;
  2988.     char_u  *fname = NULL;        /* init to shut up gcc */
  2989.     char_u  *ffname;
  2990.     int        retval = FAIL;
  2991.     char_u  *free_fname = NULL;
  2992.  
  2993.     ffname = eap->arg;
  2994.     if (*ffname == NUL)
  2995.     other = FALSE;
  2996.     else
  2997.     {
  2998.     fname = ffname;
  2999.     free_fname = fix_fname(ffname);
  3000.     /*
  3001.      * When out-of-memory, keep unexpanded file name, because we MUST be
  3002.      * able to write the file in this situation.
  3003.      */
  3004.     if (free_fname != NULL)
  3005.         ffname = free_fname;
  3006.     other = otherfile(ffname);
  3007.     }
  3008.  
  3009.     /*
  3010.      * If we have a new file, name put it in the list of alternate file names.
  3011.      */
  3012.     if (other && vim_strchr(p_cpo, CPO_ALTWRITE) != NULL)
  3013.     setaltfname(ffname, fname, (linenr_t)1);
  3014.  
  3015.     /*
  3016.      * writing to the current file is not allowed in readonly mode
  3017.      * and need a file name
  3018.      */
  3019.     if (!other && (check_readonly(eap->forceit) || check_fname() == FAIL))
  3020.     goto theend;
  3021.  
  3022.     if (!other)
  3023.     {
  3024.     ffname = curbuf->b_ffname;
  3025.     fname = curbuf->b_fname;
  3026.     /*
  3027.      * Not writing the whole file is only allowed with '!'.
  3028.      */
  3029.     if (       (eap->line1 != 1
  3030.             || eap->line2 != curbuf->b_ml.ml_line_count)
  3031.         && !eap->forceit
  3032.         && !eap->append
  3033.         && !p_wa)
  3034.     {
  3035.         EMSG("Use ! to write partial buffer");
  3036.         goto theend;
  3037.     }
  3038.     }
  3039.  
  3040.     /*
  3041.      * write to other file or b_notedited set or not writing the whole file:
  3042.      * overwriting only allowed with '!'
  3043.      */
  3044.     if (       (other
  3045.         || curbuf->b_notedited)
  3046.         && !eap->forceit
  3047.         && !eap->append
  3048.         && !p_wa
  3049.         && vim_fexists(ffname))
  3050.     {
  3051. #ifdef UNIX
  3052.         /* with UNIX it is possible to open a directory */
  3053.     if (mch_isdir(ffname))
  3054.         EMSG2("\"%s\" is a directory", ffname);
  3055.     else
  3056. #endif
  3057.         emsg(e_exists);
  3058.     goto theend;
  3059.     }
  3060.     retval = (buf_write(curbuf, ffname, fname, eap->line1, eap->line2,
  3061.                      eap->append, eap->forceit, TRUE, FALSE));
  3062. theend:
  3063.     vim_free(free_fname);
  3064.     return retval;
  3065. }
  3066.  
  3067. /*
  3068.  * try to abandon current file and edit a new or existing file
  3069.  * 'fnum' is the number of the file, if zero use ffname/sfname
  3070.  *
  3071.  * return 1 for "normal" error, 2 for "not written" error, 0 for success
  3072.  * -1 for succesfully opening another file
  3073.  * 'lnum' is the line number for the cursor in the new file (if non-zero).
  3074.  */
  3075.     int
  3076. getfile(fnum, ffname, sfname, setpm, lnum, forceit)
  3077.     int        fnum;
  3078.     char_u    *ffname;
  3079.     char_u    *sfname;
  3080.     int        setpm;
  3081.     linenr_t    lnum;
  3082.     int        forceit;
  3083. {
  3084.     int        other;
  3085.     int        retval;
  3086.     char_u    *free_me = NULL;
  3087.  
  3088.     if (fnum == 0)
  3089.     {
  3090.     fname_expand(&ffname, &sfname);    /* make ffname full path, set sfname */
  3091.     other = otherfile(ffname);
  3092.     free_me = ffname;        /* has been allocated, free() later */
  3093.     }
  3094.     else
  3095.     other = (fnum != curbuf->b_fnum);
  3096.  
  3097.     if (other)
  3098.     ++no_wait_return;        /* don't wait for autowrite message */
  3099.     if (other && !forceit && curbuf->b_nwindows == 1 &&
  3100.         !p_hid && curbuf_changed() && autowrite(curbuf, forceit) == FAIL)
  3101.     {
  3102.     if (other)
  3103.         --no_wait_return;
  3104.     emsg(e_nowrtmsg);
  3105.     retval = 2;    /* file has been changed */
  3106.     goto theend;
  3107.     }
  3108.     if (other)
  3109.     --no_wait_return;
  3110.     if (setpm)
  3111.     setpcmark();
  3112.     if (!other)
  3113.     {
  3114.     if (lnum != 0)
  3115.         curwin->w_cursor.lnum = lnum;
  3116.     check_cursor_lnum();
  3117.     beginline(BL_SOL | BL_FIX);
  3118.     retval = 0;    /* it's in the same file */
  3119.     }
  3120.     else if (do_ecmd(fnum, ffname, sfname, NULL, lnum,
  3121.         (p_hid ? ECMD_HIDE : 0) + (forceit ? ECMD_FORCEIT : 0)) == OK)
  3122.     retval = -1;    /* opened another file */
  3123.     else
  3124.     retval = 1;    /* error encountered */
  3125.  
  3126. theend:
  3127.     vim_free(free_me);
  3128.     return retval;
  3129. }
  3130.  
  3131. /*
  3132.  * start editing a new file
  3133.  *
  3134.  *     fnum: file number; if zero use ffname/sfname
  3135.  *   ffname: the file name
  3136.  *        - full path if sfname used,
  3137.  *        - any file name if sfname is NULL
  3138.  *        - empty string to re-edit with the same file name (but may be
  3139.  *            in a different directory)
  3140.  *        - NULL to start an empty buffer
  3141.  *   sfname: the short file name (or NULL)
  3142.  *  command: the command to be executed after loading the file
  3143.  *  newlnum: put cursor on this line number (if possible)
  3144.  *    flags:
  3145.  *       ECMD_HIDE: if TRUE don't free the current buffer
  3146.  *     ECMD_SET_HELP: set b_help flag of (new) buffer before opening file
  3147.  *     ECMD_OLDBUF: use existing buffer if it exists
  3148.  *    ECMD_FORCEIT: ! used for Ex command
  3149.  *
  3150.  * return FAIL for failure, OK otherwise
  3151.  */
  3152.     int
  3153. do_ecmd(fnum, ffname, sfname, command, newlnum, flags)
  3154.     int        fnum;
  3155.     char_u    *ffname;
  3156.     char_u    *sfname;
  3157.     char_u    *command;
  3158.     linenr_t    newlnum;
  3159.     int        flags;
  3160. {
  3161.     int        other_file;        /* TRUE if editing another file */
  3162.     int        oldbuf;            /* TRUE if using existing buffer */
  3163. #ifdef AUTOCMD
  3164.     int        auto_buf = FALSE;    /* TRUE if autocommands brought us
  3165.                        into the buffer unexpectedly */
  3166. #endif
  3167.     BUF        *buf;
  3168.     char_u    *free_fname = NULL;
  3169.     int        retval = FAIL;
  3170.     long    n;
  3171.  
  3172.     if (fnum != 0)
  3173.     {
  3174.     if (fnum == curbuf->b_fnum)    /* file is already being edited */
  3175.         return OK;            /* nothing to do */
  3176.     other_file = TRUE;
  3177.     }
  3178.     else
  3179.     {
  3180.         /* if no short name given, use ffname for short name */
  3181.     if (sfname == NULL)
  3182.         sfname = ffname;
  3183. #ifdef USE_FNAME_CASE
  3184. # ifdef USE_LONG_FNAME
  3185.     if (USE_LONG_FNAME)
  3186. # endif
  3187.         fname_case(sfname);        /* set correct case for short file name */
  3188. #endif
  3189.  
  3190.     if (ffname == NULL)
  3191.         other_file = TRUE;
  3192.                         /* there is no file name */
  3193.     else if (*ffname == NUL && curbuf->b_ffname == NULL)
  3194.         other_file = FALSE;
  3195.     else
  3196.     {
  3197.         if (*ffname == NUL)            /* re-edit with same file name */
  3198.         {
  3199.         ffname = curbuf->b_ffname;
  3200.         sfname = curbuf->b_fname;
  3201.         }
  3202.         free_fname = fix_fname(ffname); /* may expand to full path name */
  3203.         if (free_fname != NULL)
  3204.         ffname = free_fname;
  3205.         other_file = otherfile(ffname);
  3206.     }
  3207.     }
  3208. /*
  3209.  * if the file was changed we may not be allowed to abandon it
  3210.  * - if we are going to re-edit the same file
  3211.  * - or if we are the only window on this file and if ECMD_HIDE is FALSE
  3212.  */
  3213.     if (((!other_file && !(flags & ECMD_OLDBUF)) ||
  3214.         (curbuf->b_nwindows == 1 && !(flags & ECMD_HIDE))) &&
  3215.         check_changed(curbuf, FALSE, !other_file, (flags & ECMD_FORCEIT)))
  3216.     {
  3217.     if (fnum == 0 && other_file && ffname != NULL)
  3218.         setaltfname(ffname, sfname, newlnum);
  3219.     goto theend;
  3220.     }
  3221.  
  3222. /*
  3223.  * End Visual mode before switching to another buffer, so the text can be
  3224.  * copied into the GUI selection buffer.
  3225.  */
  3226.     if (VIsual_active)
  3227.     end_visual_mode();
  3228.  
  3229. /*
  3230.  * If we are starting to edit another file, open a (new) buffer.
  3231.  * Otherwise we re-use the current buffer.
  3232.  */
  3233.     if (other_file)
  3234.     {
  3235.     curwin->w_alt_fnum = curbuf->b_fnum;
  3236.     buflist_altlnum();
  3237.  
  3238.     if (fnum)
  3239.         buf = buflist_findnr(fnum);
  3240.     else
  3241.         buf = buflist_new(ffname, sfname, 1L, TRUE);
  3242.     if (buf == NULL)
  3243.         goto theend;
  3244.     if (buf->b_ml.ml_mfp == NULL)        /* no memfile yet */
  3245.     {
  3246.         oldbuf = FALSE;
  3247.         buf->b_nwindows = 0;
  3248.     }
  3249.     else                    /* existing memfile */
  3250.     {
  3251.         oldbuf = TRUE;
  3252.         buf_check_timestamp(buf);
  3253.     }
  3254.  
  3255.     /*
  3256.      * Make the (new) buffer the one used by the current window.
  3257.      * If the old buffer becomes unused, free it if ECMD_HIDE is FALSE.
  3258.      * If the current buffer was empty and has no file name, curbuf
  3259.      * is returned by buflist_new().
  3260.      */
  3261.     if (buf != curbuf)
  3262.     {
  3263. #ifdef AUTOCMD
  3264.         BUF        *old_curbuf;
  3265.         char_u  *new_name = NULL;
  3266.  
  3267.         /*
  3268.          * Be careful: The autocommands may delete any buffer and change
  3269.          * the current buffer.
  3270.          * - If the buffer we are going to edit is deleted, give up.
  3271.          * - If we ended up in the new buffer already, need to skip a few
  3272.          *     things, set auto_buf.
  3273.          */
  3274.         old_curbuf = curbuf;
  3275.         if (buf->b_fname != NULL)
  3276.         new_name = vim_strsave(buf->b_fname);
  3277.         apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE);
  3278.         if (!buf_valid(buf))    /* new buffer has been deleted */
  3279.         {
  3280.         EMSG2("Autocommands unexpectedly deleted new buffer %s",
  3281.             new_name == NULL ? (char_u *)"" : new_name);
  3282.         vim_free(new_name);
  3283.         goto theend;
  3284.         }
  3285.         vim_free(new_name);
  3286.         if (buf == curbuf)        /* already in new buffer */
  3287.         auto_buf = TRUE;
  3288.         else
  3289.         {
  3290.         if (curbuf == old_curbuf)
  3291. #endif
  3292.             buf_copy_options(curbuf, buf, BCO_ENTER);
  3293.         close_buffer(curwin, curbuf, !(flags & ECMD_HIDE), FALSE);
  3294.         curwin->w_buffer = buf;
  3295.         curbuf = buf;
  3296.         ++curbuf->b_nwindows;
  3297.         /* set 'fileformat' */
  3298.         if (*p_ffs && !oldbuf)
  3299.             set_fileformat(default_fileformat());
  3300. #ifdef AUTOCMD
  3301.         }
  3302. #endif
  3303.     }
  3304.     else
  3305.         ++curbuf->b_nwindows;
  3306.  
  3307.     curwin->w_pcmark.lnum = 1;
  3308.     curwin->w_pcmark.col = 0;
  3309.     }
  3310.     else
  3311.     {
  3312.     if (check_fname() == FAIL)
  3313.         goto theend;
  3314.     oldbuf = (flags & ECMD_OLDBUF);
  3315.     }
  3316.  
  3317. /*
  3318.  * If we get here we are sure to start editing
  3319.  */
  3320.     /* don't redraw until the cursor is in the right line */
  3321.     ++RedrawingDisabled;
  3322.     if (flags & ECMD_SET_HELP)
  3323.     curbuf->b_help = TRUE;
  3324.  
  3325. /*
  3326.  * other_file    oldbuf
  3327.  *  FALSE    FALSE        re-edit same file, buffer is re-used
  3328.  *  FALSE    TRUE        re-edit same file, nothing changes
  3329.  *  TRUE    FALSE        start editing new file, new buffer
  3330.  *  TRUE    TRUE        start editing in existing buffer (nothing to do)
  3331.  */
  3332.     if (!other_file && !oldbuf)        /* re-use the buffer */
  3333.     {
  3334.     if (newlnum == 0)
  3335.         newlnum = curwin->w_cursor.lnum;
  3336.     buf_freeall(curbuf, FALSE);    /* free all things for buffer */
  3337.     buf_clear(curbuf);
  3338.     curbuf->b_op_start.lnum = 0;    /* clear '[ and '] marks */
  3339.     curbuf->b_op_end.lnum = 0;
  3340.     }
  3341.  
  3342.     /*
  3343.      * Reset cursor position, could be used by autocommands.
  3344.      */
  3345.     adjust_cursor();
  3346.  
  3347.     /*
  3348.      * Check if we are editing the w_arg_idx file in the argument list.
  3349.      */
  3350.     check_arg_idx();
  3351.  
  3352. #ifdef AUTOCMD
  3353.     if (!auto_buf)
  3354. #endif
  3355.     {
  3356.     /*
  3357.      * Set cursor and init window before reading the file and executing
  3358.      * autocommands.  This allows for the autocommands to position the
  3359.      * cursor.
  3360.      */
  3361.     win_init(curwin);
  3362.  
  3363.     /*
  3364.      * Careful: open_buffer() and apply_autocmds() may change the current
  3365.      * buffer and window.
  3366.      */
  3367.     if (!oldbuf)                /* need to read the file */
  3368.     {
  3369.         curbuf->b_flags |= BF_CHECK_RO; /* set/reset 'ro' flag */
  3370.         (void)open_buffer(FALSE);
  3371.     }
  3372. #ifdef AUTOCMD
  3373.     else
  3374.         apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE);
  3375.     check_arg_idx();
  3376. #endif
  3377.     maketitle();
  3378.     }
  3379.  
  3380.     if (command == NULL)
  3381.     {
  3382.     if (newlnum)
  3383.     {
  3384.         curwin->w_cursor.lnum = newlnum;
  3385.         check_cursor_lnum();
  3386.         beginline(BL_SOL | BL_FIX);
  3387.     }
  3388.     else
  3389.     {
  3390.         if (exmode_active)
  3391.         {
  3392.         curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  3393.         check_cursor_lnum();
  3394.         }
  3395.         beginline(BL_WHITE | BL_FIX);
  3396.     }
  3397.     }
  3398.  
  3399.     /* Check if cursors in other windows on the same buffer are still valid */
  3400.     check_lnums(FALSE);
  3401.  
  3402.     /*
  3403.      * Did not read the file, need to show some info about the file.
  3404.      * Do this after setting the cursor.
  3405.      */
  3406.     if (oldbuf
  3407. #ifdef AUTOCMD
  3408.         && !auto_buf
  3409. #endif
  3410.                 )
  3411.     fileinfo(FALSE, TRUE, FALSE);
  3412.  
  3413.     if (command != NULL)
  3414.     do_cmdline(command, NULL, NULL, DOCMD_VERBOSE);
  3415.     --RedrawingDisabled;
  3416.     if (!skip_redraw)
  3417.     {
  3418.     n = p_so;
  3419.     if (command == NULL)
  3420.         p_so = 999;            /* force cursor halfway the window */
  3421.     update_topline();
  3422.     p_so = n;
  3423.     update_curbuf(NOT_VALID);    /* redraw now */
  3424.     }
  3425.  
  3426.     if (p_im)
  3427.     need_start_insertmode = TRUE;
  3428.     retval = OK;
  3429.  
  3430. theend:
  3431.     vim_free(free_fname);
  3432.     return retval;
  3433. }
  3434.  
  3435. #ifdef QUICKFIX
  3436.     static void
  3437. do_make(arg)
  3438.     char_u *arg;
  3439. {
  3440.     char_u    *name;
  3441.  
  3442.     autowrite_all();
  3443.     name = get_mef_name(TRUE);
  3444.     if (name == NULL)
  3445.     return;
  3446.     vim_remove(name);        /* in case it's not unique */
  3447.  
  3448.     /*
  3449.      * If 'shellpipe' empty: don't redirect to 'errorfile'.
  3450.      */
  3451.     if (*p_sp == NUL)
  3452.     sprintf((char *)IObuff, "%s%s%s", p_shq, arg, p_shq);
  3453.     else
  3454.     sprintf((char *)IObuff, "%s%s%s %s %s", p_shq, arg, p_shq, p_sp, name);
  3455.     /*
  3456.      * Output a newline if there's something else than the :make command that
  3457.      * was typed (in which case the cursor is in column 0).
  3458.      */
  3459.     if (msg_col != 0)
  3460.     msg_putchar('\n');
  3461.     MSG_PUTS(":!");
  3462.     msg_outtrans(IObuff);        /* show what we are doing */
  3463.  
  3464.     /* let the shell know if we are redirecting output or not */
  3465.     do_shell(IObuff, *p_sp ? SHELL_DOOUT : 0);
  3466.  
  3467. #ifdef AMIGA
  3468.     out_flush();
  3469.         /* read window status report and redraw before message */
  3470.     (void)char_avail();
  3471. #endif
  3472.  
  3473.     if (qf_init(name) > 0)
  3474.     qf_jump(0, 0, FALSE);        /* display first error */
  3475.  
  3476.     vim_remove(name);
  3477.     vim_free(name);
  3478. }
  3479.  
  3480. /*
  3481.  * Return the name for the errorfile, in allocated memory.
  3482.  * When "newname" is TRUE, find a new unique name when 'makeef' contains
  3483.  * "##".  Returns NULL for error.
  3484.  */
  3485.     static char_u *
  3486. get_mef_name(newname)
  3487.     int        newname;
  3488. {
  3489.     char_u    *p;
  3490.     char_u    *name;
  3491.     static int    start = -1;
  3492.     static int    off = 0;
  3493.  
  3494.     if (*p_mef == NUL)
  3495.     {
  3496.     EMSG("makeef option not set");
  3497.     return NULL;
  3498.     }
  3499.  
  3500.     for (p = p_mef; *p; ++p)
  3501.     if (p[0] == '#' && p[1] == '#')
  3502.         break;
  3503.  
  3504.     if (*p == NUL)
  3505.     return vim_strsave(p_mef);
  3506.  
  3507.     /* When "newname" set: keep trying until the name doesn't exist yet. */
  3508.     for (;;)
  3509.     {
  3510.     if (newname)
  3511.     {
  3512.         if (start == -1)
  3513.         start = mch_get_pid();
  3514.         ++off;
  3515.     }
  3516.  
  3517.     name = alloc((unsigned)STRLEN(p_mef) + 30);
  3518.     if (name == NULL)
  3519.         break;
  3520.     STRCPY(name, p_mef);
  3521.     sprintf((char *)name + (p - p_mef), "%d%d", start, off);
  3522.     STRCAT(name, p + 2);
  3523.     if (!newname || mch_getperm(name) < 0)
  3524.         break;
  3525.     vim_free(name);
  3526.     }
  3527.     return name;
  3528. }
  3529.  
  3530. /*
  3531.  * ":cfile" command.
  3532.  */
  3533.     static void
  3534. do_cfile(eap)
  3535.     EXARG    *eap;
  3536. {
  3537.     if (*eap->arg != NUL)
  3538.     set_string_option_direct((char_u *)"ef", -1, eap->arg, TRUE);
  3539.     if (qf_init(p_ef) > 0)
  3540.     qf_jump(0, 0, eap->forceit);        /* display first error */
  3541. }
  3542. #endif /* QUICKFIX */
  3543.  
  3544. /*
  3545.  * Redefine the argument list to 'str'.
  3546.  *
  3547.  * Return FAIL for failure, OK otherwise.
  3548.  */
  3549.     static int
  3550. do_arglist(str)
  3551.     char_u *str;
  3552. {
  3553.     int        new_count = 0;
  3554.     char_u  **new_files = NULL;
  3555.     int        exp_count;
  3556.     char_u  **exp_files;
  3557.     char_u  **t;
  3558.     char_u  *p;
  3559.     int        inquote;
  3560.     int        i;
  3561.  
  3562.     while (*str)
  3563.     {
  3564.     /*
  3565.      * create a new entry in new_files[]
  3566.      */
  3567.     t = (char_u **)lalloc((long_u)(sizeof(char_u *) * (new_count + 1)),
  3568.                                     TRUE);
  3569.     if (t != NULL)
  3570.         for (i = new_count; --i >= 0; )
  3571.         t[i] = new_files[i];
  3572.     vim_free(new_files);
  3573.     if (t == NULL)
  3574.         return FAIL;
  3575.     new_files = t;
  3576.     new_files[new_count++] = str;
  3577.  
  3578.     /*
  3579.      * isolate one argument, taking quotes
  3580.      */
  3581.     inquote = FALSE;
  3582.     for (p = str; *str; ++str)
  3583.     {
  3584.         /*
  3585.          * for MSDOS et.al. a backslash is part of a file name.
  3586.          * Only skip ", space and tab.
  3587.          */
  3588.         if (rem_backslash(str))
  3589.         *p++ = *++str;
  3590.         else
  3591.         {
  3592.         if (!inquote && vim_isspace(*str))
  3593.             break;
  3594.         if (*str == '"')
  3595.             inquote ^= TRUE;
  3596.         else
  3597.             *p++ = *str;
  3598.         }
  3599.     }
  3600.     str = skipwhite(str);
  3601.     *p = NUL;
  3602.     }
  3603.  
  3604.     i = expand_wildcards(new_count, new_files, &exp_count, &exp_files,
  3605.                           EW_DIR|EW_FILE|EW_NOTFOUND);
  3606.     vim_free(new_files);
  3607.     if (i == FAIL)
  3608.     return FAIL;
  3609.     if (exp_count == 0)
  3610.     {
  3611.     emsg(e_nomatch);
  3612.     return FAIL;
  3613.     }
  3614.     FreeWild(arg_file_count, arg_files);
  3615.     arg_files = exp_files;
  3616.     arg_file_count = exp_count;
  3617.     arg_had_last = FALSE;
  3618.  
  3619.     /*
  3620.      * put all file names in the buffer list
  3621.      */
  3622.     for (i = 0; i < arg_file_count; ++i)
  3623.     (void)buflist_add(arg_files[i]);
  3624.  
  3625.     return OK;
  3626. }
  3627.  
  3628. /*
  3629.  * Check if we are editing the w_arg_idx file in the argument list.
  3630.  */
  3631.     void
  3632. check_arg_idx()
  3633. {
  3634.     if (arg_file_count > 1
  3635.         && (curbuf->b_ffname == NULL
  3636.         || curwin->w_arg_idx >= arg_file_count
  3637.         || !(fullpathcmp(arg_files[curwin->w_arg_idx],
  3638.                      curbuf->b_ffname, TRUE) & FPC_SAME)))
  3639.     curwin->w_arg_idx_invalid = TRUE;
  3640.     else
  3641.     curwin->w_arg_idx_invalid = FALSE;
  3642. }
  3643.  
  3644.     int
  3645. ends_excmd(c)
  3646.     int        c;
  3647. {
  3648.     return (c == NUL || c == '|' || c == '\"' || c == '\n');
  3649. }
  3650.  
  3651. /*
  3652.  * Return the next command, after the first '|' or '\n'.
  3653.  * Return NULL if not found.
  3654.  */
  3655.     char_u *
  3656. find_nextcmd(p)
  3657.     char_u    *p;
  3658. {
  3659.     while (*p != '|' && *p != '\n')
  3660.     {
  3661.     if (*p == NUL)
  3662.         return NULL;
  3663.     ++p;
  3664.     }
  3665.     return (p + 1);
  3666. }
  3667.  
  3668. /*
  3669.  * Check if *p is a separator between Ex commands.
  3670.  * Return NULL if it isn't, (p + 1) if it is.
  3671.  */
  3672.     char_u *
  3673. check_nextcmd(p)
  3674.     char_u    *p;
  3675. {
  3676.     p = skipwhite(p);
  3677.     if (*p == '|' || *p == '\n')
  3678.     return (p + 1);
  3679.     else
  3680.     return NULL;
  3681. }
  3682.  
  3683. /*
  3684.  * - if there are more files to edit
  3685.  * - and this is the last window
  3686.  * - and forceit not used
  3687.  * - and not repeated twice on a row
  3688.  *    return FAIL and give error message if 'message' TRUE
  3689.  * return OK otherwise
  3690.  */
  3691.     static int
  3692. check_more(message, forceit)
  3693.     int message;        /* when FALSE check only, no messages */
  3694.     int forceit;
  3695. {
  3696.     if (!forceit && only_one_window() && arg_file_count > 1 && !arg_had_last &&
  3697.                     quitmore == 0)
  3698.     {
  3699.     if (message)
  3700.     {
  3701.         EMSGN("%ld more files to edit",
  3702.                       arg_file_count - curwin->w_arg_idx - 1);
  3703.         quitmore = 2;        /* next try to quit is allowed */
  3704.     }
  3705.     return FAIL;
  3706.     }
  3707.     return OK;
  3708. }
  3709.  
  3710. /*
  3711.  * Structure used to store info for each sourced file.
  3712.  * It is shared between do_source() and getsourceline().
  3713.  * This is required, because it needs to be handed to do_cmdline() and
  3714.  * sourcing can be done recursively.
  3715.  */
  3716. struct source_cookie
  3717. {
  3718.     FILE    *fp;        /* opened file for sourcing */
  3719. #ifdef USE_CRNL
  3720.     int        fileformat;    /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */
  3721.     int        error;        /* TRUE if LF found after CR-LF */
  3722. #endif
  3723. };
  3724.  
  3725. /*
  3726.  * do_source: Read the file "fname" and execute its lines as EX commands.
  3727.  *
  3728.  * This function may be called recursively!
  3729.  *
  3730.  * return FAIL if file could not be opened, OK otherwise
  3731.  */
  3732.     int
  3733. do_source(fname, check_other, is_vimrc)
  3734.     char_u    *fname;
  3735.     int        check_other;        /* check for .vimrc and _vimrc */
  3736.     int        is_vimrc;        /* call vimrc_found() when file exists */
  3737. {
  3738.     struct source_cookie    cookie;
  3739.     char_u            *save_sourcing_name;
  3740.     linenr_t            save_sourcing_lnum;
  3741.     char_u            *p;
  3742.     char_u            *fname_exp;
  3743.     int                retval = FAIL;
  3744.  
  3745.     fname_exp = expand_env_save(fname);
  3746.     if (fname_exp == NULL)
  3747.     goto theend;
  3748. #ifdef macintosh
  3749.     slash_n_colon_adjust(fname_exp);
  3750. #endif
  3751.     cookie.fp = fopen((char *)fname_exp, READBIN);
  3752.     if (cookie.fp == NULL && check_other)
  3753.     {
  3754.     /*
  3755.      * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa,
  3756.      * and ".exrc" by "_exrc" or vice versa.
  3757.      */
  3758.     p = gettail(fname_exp);
  3759.     if ((*p == '.' || *p == '_') &&
  3760.         (STRICMP(p + 1, "vimrc") == 0 ||
  3761.          STRICMP(p + 1, "gvimrc") == 0 ||
  3762.          STRICMP(p + 1, "exrc") == 0))
  3763.     {
  3764.         if (*p == '_')
  3765.         *p = '.';
  3766.         else
  3767.         *p = '_';
  3768.         cookie.fp = fopen((char *)fname_exp, READBIN);
  3769.     }
  3770.     }
  3771.  
  3772.     if (cookie.fp == NULL)
  3773.     {
  3774.     if (p_verbose > 0)
  3775.         smsg((char_u *)"could not source \"%s\"", fname);
  3776.     goto theend;
  3777.     }
  3778.  
  3779.     /*
  3780.      * The file exists.
  3781.      * - In verbose mode, give a message.
  3782.      * - For a vimrc file, may want to set 'compatible', call vimrc_found().
  3783.      */
  3784.     if (p_verbose > 0)
  3785.     smsg((char_u *)"sourcing \"%s\"", fname);
  3786.     if (is_vimrc)
  3787.     vimrc_found();
  3788.  
  3789.  
  3790. #ifdef USE_CRNL
  3791.     /* If no automatic file format: Set default to CR-NL. */
  3792.     if (*p_ffs == NUL)
  3793.     cookie.fileformat = EOL_DOS;
  3794.     else
  3795.     cookie.fileformat = EOL_UNKNOWN;
  3796.     cookie.error = FALSE;
  3797. #endif
  3798.  
  3799.     /*
  3800.      * Keep the sourcing name, for recursive calls.
  3801.      */
  3802.     save_sourcing_name = sourcing_name;
  3803.     save_sourcing_lnum = sourcing_lnum;
  3804.     sourcing_name = fname_exp;
  3805.     sourcing_lnum = 0;
  3806.  
  3807.     /*
  3808.      * Call do_cmdline, which will call getsourceline() to get the lines.
  3809.      */
  3810.     do_cmdline(NULL, getsourceline, (void *)&cookie,
  3811.                      DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT);
  3812.  
  3813.     fclose(cookie.fp);
  3814.     if (got_int)
  3815.     emsg(e_interr);
  3816.     sourcing_name = save_sourcing_name;
  3817.     sourcing_lnum = save_sourcing_lnum;
  3818.     retval = OK;
  3819.  
  3820. theend:
  3821.     vim_free(fname_exp);
  3822.     return retval;
  3823. }
  3824.  
  3825. /*
  3826.  * Get one full line from a sourced file.
  3827.  * Called by do_source() and do_cmdline().
  3828.  *
  3829.  * Return a pointer to the line in allocated memory.
  3830.  * Return NULL for end-of-file or some error.
  3831.  */
  3832. /* ARGSUSED */
  3833.     char_u *
  3834. getsourceline(c, cookie, indent)
  3835.     int        c;            /* not used */
  3836.     void    *cookie;
  3837.     int        indent;        /* not used */
  3838. {
  3839.     struct source_cookie    *sp = (struct source_cookie *)cookie;
  3840.     struct growarray        ga;
  3841.     int                len;
  3842.     char_u            *buf;
  3843. #ifdef USE_CRNL
  3844.     int                has_cr;        /* CR-LF found */
  3845. #endif
  3846.     int                have_read = FALSE;
  3847.  
  3848.     /* use a growarray to store the sourced line */
  3849.     ga_init(&ga);
  3850.     ga.ga_itemsize = 1;
  3851.     ga.ga_growsize = 200;
  3852.  
  3853.     /*
  3854.      * Loop until there is a finished line (or end-of-file).
  3855.      */
  3856.     sourcing_lnum++;
  3857.     for (;;)
  3858.     {
  3859.     /* make room to read at least 80 (more) characters */
  3860.     if (ga_grow(&ga, 80) == FAIL)
  3861.         break;
  3862.     buf = (char_u *)ga.ga_data;
  3863.  
  3864.     if (fgets((char *)buf + ga.ga_len, ga.ga_room, sp->fp) == NULL
  3865.                                    || got_int)
  3866.         break;
  3867.  
  3868.     len = STRLEN(buf);
  3869. #ifdef USE_CRNL
  3870.     /* Ignore a trailing CTRL-Z, when in Dos mode.    Only recognize the
  3871.      * CTRL-Z by its own, or after a NL. */
  3872.     if (       (len == 1 || (len >= 2 && buf[len - 2] == '\n'))
  3873.         && sp->fileformat == EOL_DOS
  3874.         && buf[len - 1] == Ctrl('Z'))
  3875.     {
  3876.         buf[len - 1] = NUL;
  3877.         break;
  3878.     }
  3879. #endif
  3880.     have_read = TRUE;
  3881.     ga.ga_room -= len - ga.ga_len;
  3882.     ga.ga_len = len;
  3883.  
  3884.     /* If the line was longer than the buffer, read more. */
  3885.     if (ga.ga_room == 1 && buf[len - 1] != '\n')
  3886.         continue;
  3887.  
  3888.     if (len >= 1 && buf[len - 1] == '\n')    /* remove trailing NL */
  3889.     {
  3890. #ifdef USE_CRNL
  3891.         has_cr = (len >= 2 && buf[len - 2] == '\r');
  3892.         if (sp->fileformat == EOL_UNKNOWN)
  3893.         {
  3894.         if (has_cr)
  3895.             sp->fileformat = EOL_DOS;
  3896.         else
  3897.             sp->fileformat = EOL_UNIX;
  3898.         }
  3899.  
  3900.         if (sp->fileformat == EOL_DOS)
  3901.         {
  3902.         if (has_cr)        /* replace trailing CR */
  3903.         {
  3904.             buf[len - 2] = '\n';
  3905.             --len;
  3906.             --ga.ga_len;
  3907.             ++ga.ga_room;
  3908.         }
  3909.         else        /* lines like ":map xx yy^M" will have failed */
  3910.         {
  3911.             if (!sp->error)
  3912.             EMSG("Warning: Wrong line separator, ^M may be missing");
  3913.             sp->error = TRUE;
  3914.             sp->fileformat = EOL_UNIX;
  3915.         }
  3916.         }
  3917. #endif
  3918.         /* The '\n' is escaped if there is an odd number of ^V's just
  3919.          * before it, first set "c" just before the 'V's and then check
  3920.          * len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo */
  3921.         for (c = len - 2; c >= 0 && buf[c] == Ctrl('V'); c--)
  3922.         ;
  3923.         if ((len & 1) != (c & 1))    /* escaped NL, read more */
  3924.         {
  3925.         sourcing_lnum++;
  3926.         continue;
  3927.         }
  3928.  
  3929.         buf[len - 1] = NUL;        /* remove the NL */
  3930.     }
  3931.  
  3932.     /*
  3933.      * Check for ^C here now and then, so recursive :so can be broken.
  3934.      */
  3935.     line_breakcheck();
  3936.     break;
  3937.     }
  3938.  
  3939.     if (have_read)
  3940.     return (char_u *)ga.ga_data;
  3941.  
  3942.     vim_free(ga.ga_data);
  3943.     return NULL;
  3944. }
  3945.  
  3946. /*
  3947.  * Function given to ExpandGeneric() to obtain the list of command names.
  3948.  */
  3949.     char_u *
  3950. get_command_name(idx)
  3951.     int        idx;
  3952. {
  3953.     if (idx >= (int)CMD_SIZE)
  3954.     return NULL;
  3955.     return cmdnames[idx].cmd_name;
  3956. }
  3957.  
  3958. /*
  3959.  * Call this function if we thought we were going to exit, but we won't
  3960.  * (because of an error).  May need to restore the terminal mode.
  3961.  */
  3962.     void
  3963. not_exiting()
  3964. {
  3965.     exiting = FALSE;
  3966.     if (!exmode_active)
  3967.     settmode(TMODE_RAW);
  3968. }
  3969.  
  3970. /*
  3971.  * ":quit": quit current window, quit Vim if closed the last window.
  3972.  */
  3973.     static void
  3974. do_quit(eap)
  3975.     EXARG    *eap;
  3976. {
  3977.     /*
  3978.      * If there are more files or windows we won't exit.
  3979.      */
  3980.     if (check_more(FALSE, eap->forceit) == OK && only_one_window())
  3981.     exiting = TRUE;
  3982.     if ((!p_hid && check_changed(curbuf, FALSE, FALSE, eap->forceit))
  3983.         || check_more(TRUE, eap->forceit) == FAIL
  3984.         || (only_one_window()
  3985.         && !eap->forceit && check_changed_any()))
  3986.     {
  3987.     not_exiting();
  3988.     }
  3989.     else
  3990.     {
  3991.     if (only_one_window())        /* quit last window */
  3992.         getout(0);
  3993.     close_window(curwin, !p_hid || eap->forceit); /* may free buffer */
  3994.     }
  3995. }
  3996.  
  3997. /*
  3998.  * ":qall": try to quit all windows
  3999.  */
  4000.     static void
  4001. do_quit_all(forceit)
  4002.     int        forceit;
  4003. {
  4004.     exiting = TRUE;
  4005.     if (forceit || !check_changed_any())
  4006.     getout(0);
  4007.     not_exiting();
  4008. }
  4009.  
  4010. /*
  4011.  * ":close": close current window, unless it is the last one
  4012.  */
  4013.     static void
  4014. do_close(eap)
  4015.     EXARG    *eap;
  4016. {
  4017.     int        need_hide;
  4018.  
  4019.     need_hide = (buf_changed(curbuf) && curbuf->b_nwindows <= 1);
  4020.     if (need_hide && !p_hid && !eap->forceit)
  4021.     emsg(e_nowrtmsg);
  4022.     else
  4023.     close_window(curwin, !need_hide);        /* may free buffer */
  4024. }
  4025.  
  4026. /*
  4027.  * ":stop" and ":suspend": Suspend Vim.
  4028.  */
  4029.     static void
  4030. do_suspend(forceit)
  4031.     int        forceit;
  4032. {
  4033.     /*
  4034.      * Disallow suspending for "rvim".
  4035.      */
  4036.     if (!check_restricted()
  4037. #ifdef WIN32
  4038.     /*
  4039.      * Check if external commands are allowed now.
  4040.      */
  4041.     && can_end_termcap_mode(TRUE)
  4042. #endif
  4043.                     )
  4044.     {
  4045.     if (!forceit)
  4046.         autowrite_all();
  4047.     windgoto((int)Rows - 1, 0);
  4048.     out_char('\n');
  4049.     out_flush();
  4050.     stoptermcap();
  4051.     mch_restore_title(3);    /* restore window titles */
  4052.     ui_suspend();        /* call machine specific function */
  4053.     maketitle();
  4054.     starttermcap();
  4055.     scroll_start();        /* scroll screen before redrawing */
  4056.     must_redraw = CLEAR;
  4057.     set_winsize(0, 0, FALSE); /* May have resized window */
  4058.     }
  4059. }
  4060.  
  4061. /*
  4062.  * ":exit", ":xit" and ":wq": Write file and exit Vim.
  4063.  */
  4064.     static void
  4065. do_exit(eap)
  4066.     EXARG    *eap;
  4067. {
  4068.     /*
  4069.      * if more files or windows we won't exit
  4070.      */
  4071.     if (check_more(FALSE, eap->forceit) == OK && only_one_window())
  4072.     exiting = TRUE;
  4073.     if (       ((eap->cmdidx == CMD_wq
  4074.             || curbuf_changed())
  4075.         && do_write(eap) == FAIL)
  4076.         || check_more(TRUE, eap->forceit) == FAIL
  4077.         || (only_one_window()
  4078.         && !eap->forceit && check_changed_any()))
  4079.     {
  4080.     not_exiting();
  4081.     }
  4082.     else
  4083.     {
  4084.     if (only_one_window())        /* quit last window, exit Vim */
  4085.         getout(0);
  4086.     close_window(curwin, !p_hid); /* quit current window, may free buffer */
  4087.     }
  4088. }
  4089.  
  4090. /*
  4091.  * ":wall", ":wqall" and ":xall": Write all changed files (and exit).
  4092.  */
  4093.     static void
  4094. do_wqall(eap)
  4095.     EXARG    *eap;
  4096. {
  4097.     BUF        *buf;
  4098.     int        error = 0;
  4099.  
  4100.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  4101.     {
  4102.     if (buf_changed(buf))
  4103.     {
  4104.         if (buf->b_ffname == NULL)
  4105.         {
  4106.         emsg(e_noname);
  4107.         ++error;
  4108.         }
  4109.         else if (!eap->forceit && buf->b_p_ro)
  4110.         {
  4111.         EMSG2("\"%s\" is readonly, use ! to write anyway",
  4112.                                 buf->b_fname);
  4113.         ++error;
  4114.         }
  4115.         else
  4116.         {
  4117.         if (buf_write_all(buf) == FAIL)
  4118.             ++error;
  4119. #ifdef AUTOCMD
  4120.         /* an autocommand may have deleted the buffer */
  4121.         if (!buf_valid(buf))
  4122.             buf = firstbuf;
  4123. #endif
  4124.         }
  4125.     }
  4126.     }
  4127.     if (exiting)
  4128.     {
  4129.     if (!error)
  4130.         getout(0);        /* exit Vim */
  4131.     not_exiting();
  4132.     }
  4133. }
  4134.  
  4135.     static void
  4136. do_print(eap)
  4137.     EXARG    *eap;
  4138. {
  4139.     for ( ;!got_int; ui_breakcheck())
  4140.     {
  4141.     print_line(eap->line1,
  4142.            (eap->cmdidx == CMD_number || eap->cmdidx == CMD_pound));
  4143.     if (++eap->line1 > eap->line2)
  4144.         break;
  4145.     out_flush();        /* show one line at a time */
  4146.     }
  4147.     setpcmark();
  4148.     /* put cursor at last line */
  4149.     curwin->w_cursor.lnum = eap->line2;
  4150.     beginline(BL_SOL | BL_FIX);
  4151.  
  4152.     ex_no_reprint = TRUE;
  4153. }
  4154.  
  4155. /*
  4156.  * Edit file "argn" from the arguments.
  4157.  */
  4158.     static void
  4159. do_argfile(eap, argn)
  4160.     EXARG   *eap;
  4161.     int        argn;
  4162. {
  4163.     int        other;
  4164.     char_u    *p;
  4165.     char_u    *ffname;
  4166.     BUF        *buf;
  4167.  
  4168.     if (argn < 0 || argn >= arg_file_count)
  4169.     {
  4170.     if (arg_file_count <= 1)
  4171.         EMSG("There is only one file to edit");
  4172.     else if (argn < 0)
  4173.         EMSG("Cannot go before first file");
  4174.     else
  4175.         EMSG("Cannot go beyond last file");
  4176.     }
  4177.     else
  4178.     {
  4179.     setpcmark();
  4180.     if (*eap->cmd == 's')        /* split window first */
  4181.     {
  4182.         if (win_split(0, FALSE, FALSE) == FAIL)
  4183.         return;
  4184.     }
  4185.     else
  4186.     {
  4187.         /*
  4188.          * if 'hidden' set, only check for changed file when re-editing
  4189.          * the same buffer
  4190.          */
  4191.         other = TRUE;
  4192.         if (p_hid)
  4193.         {
  4194.         p = fix_fname(arg_files[argn]);
  4195.         other = otherfile(p);
  4196.         vim_free(p);
  4197.         }
  4198.         if ((!p_hid || !other)
  4199.              && check_changed(curbuf, TRUE, !other, eap->forceit))
  4200.         return;
  4201.     }
  4202.  
  4203.     curwin->w_arg_idx = argn;
  4204.     if (argn == arg_file_count - 1)
  4205.         arg_had_last = TRUE;
  4206.  
  4207.     /*
  4208.      * If no line number given, use the last known line number.
  4209.      */
  4210.     if (eap->do_ecmd_lnum == 0)
  4211.     {
  4212.         ffname = fix_fname(arg_files[curwin->w_arg_idx]);
  4213.         if (ffname != NULL)
  4214.         {
  4215.         buf = buflist_findname(ffname);
  4216.         if (buf != NULL)
  4217.             eap->do_ecmd_lnum = buflist_findlnum(buf);
  4218.         vim_free(ffname);
  4219.         }
  4220.     }
  4221.  
  4222.     (void)do_ecmd(0, arg_files[curwin->w_arg_idx],
  4223.               NULL, eap->do_ecmd_cmd, eap->do_ecmd_lnum,
  4224.               (p_hid ? ECMD_HIDE : 0) +
  4225.                        (eap->forceit ? ECMD_FORCEIT : 0));
  4226.     }
  4227. }
  4228.  
  4229. /*
  4230.  * Do ":next" command, and commands that behave like it.
  4231.  */
  4232.     static void
  4233. do_next(eap)
  4234.     EXARG    *eap;
  4235. {
  4236.     int        i;
  4237.  
  4238.     /*
  4239.      * check for changed buffer now, if this fails the argument list is not
  4240.      * redefined.
  4241.      */
  4242.     if (       p_hid
  4243.         || eap->cmdidx == CMD_snext
  4244.         || !check_changed(curbuf, TRUE, FALSE, eap->forceit))
  4245.     {
  4246.     if (*eap->arg != NUL)            /* redefine file list */
  4247.     {
  4248.         if (do_arglist(eap->arg) == FAIL)
  4249.         return;
  4250.         i = 0;
  4251.     }
  4252.     else
  4253.         i = curwin->w_arg_idx + (int)eap->line2;
  4254.     do_argfile(eap, i);
  4255.     }
  4256. }
  4257.  
  4258. #if defined(USE_GUI_WIN32) || defined(USE_GUI_BEOS) || defined(PROTO) || defined(macintosh)
  4259. /*
  4260.  * Handle a file drop. The code is here because a drop is *nearly* like an
  4261.  * :args command, but not quite (we have a list of exact filenames, so we
  4262.  * don't want to (a) parse a command line, or (b) expand wildcards. So the
  4263.  * code is very similar to :args and hence needs access to a lot of the static
  4264.  * functions in this file.
  4265.  *
  4266.  * Arguments:
  4267.  *    FILEC => the number of files dropped
  4268.  *    FILEV => the list of files dropped
  4269.  *
  4270.  * The list should be allocated using vim_alloc(), as should each item in the
  4271.  * list. This function takes over responsibility for freeing the list.
  4272.  *
  4273.  * XXX The list is made into the arg_files list. This is freed using
  4274.  * FreeWild(), which does a series of vim_free() calls, unless the two defines
  4275.  * __EMX__ and __ALWAYS_HAS_TRAILING_NUL_POINTER are set. In this case, a
  4276.  * routine _fnexplodefree() is used. This may cause problems, but as the drop
  4277.  * file functionality is (currently) Win32-specific (where these defines are
  4278.  * not set), this is not presently a problem.
  4279.  */
  4280.  
  4281. void
  4282. handle_drop(filec, filev)
  4283.     int         filec;
  4284.     char_u **filev;
  4285. {
  4286.     EXARG ea;
  4287.     int i;
  4288.     int split = FALSE;
  4289.  
  4290.     /* Check whether the current buffer is changed. If so, we will need
  4291.      * to split the current window or data could be lost.
  4292.      * We don't need to check if the 'hidden' option is set, as in this
  4293.      * case the buffer won't be lost.
  4294.      */
  4295.     if (!p_hid)
  4296.     {
  4297.     int old_emsg = emsg_off;
  4298.  
  4299.     emsg_off = TRUE;
  4300.     split = check_changed(curbuf, TRUE, FALSE, FALSE);
  4301.     emsg_off = old_emsg;
  4302.     }
  4303.  
  4304.     /*
  4305.      * Set up the new argument list.
  4306.      * This code is copied from the tail end of do_arglist()
  4307.      */
  4308.     FreeWild(arg_file_count, arg_files);
  4309.     arg_file_count = filec;
  4310.     arg_files = filev;
  4311.     arg_had_last = FALSE;
  4312.  
  4313.     for (i = 0; i < arg_file_count; ++i)
  4314.     (void)buflist_add(arg_files[i]);
  4315.  
  4316.     /*
  4317.      * Move to the first file.
  4318.      */
  4319.  
  4320.     /* Fake up a minimal "[s]next" command for do_argfile() */
  4321.     ea.cmd = (char_u *)(split ? "snext" : "next");
  4322.     ea.forceit = FALSE;
  4323.     ea.do_ecmd_cmd = NULL;
  4324.     ea.do_ecmd_lnum = 0;
  4325.  
  4326.     do_argfile(&ea, 0);
  4327. }
  4328. #endif
  4329.  
  4330. /*
  4331.  * Handle ":recover" command.
  4332.  */
  4333.     static void
  4334. do_recover(eap)
  4335.     EXARG    *eap;
  4336. {
  4337.     recoverymode = TRUE;
  4338.     if (!check_changed(curbuf, FALSE, TRUE, eap->forceit)
  4339.         && (*eap->arg == NUL || setfname(eap->arg, NULL, TRUE) == OK))
  4340.     ml_recover();
  4341.     recoverymode = FALSE;
  4342. }
  4343.  
  4344. /*
  4345.  * Handle ":args" command.
  4346.  */
  4347.     static void
  4348. do_args(eap)
  4349.     EXARG    *eap;
  4350. {
  4351.     int        i;
  4352.  
  4353.     /* ":args file": handle like :next */
  4354.     if (!ends_excmd(*eap->arg))
  4355.     do_next(eap);
  4356.     else
  4357.     {
  4358.     if (arg_file_count == 0)        /* no file name list */
  4359.     {
  4360.         if (check_fname() == OK)        /* check for no file name */
  4361.         smsg((char_u *)"[%s]", curbuf->b_ffname);
  4362.     }
  4363.     else
  4364.     {
  4365.         /*
  4366.          * Overwrite the command, in most cases there is no scrolling
  4367.          * required and no wait_return().
  4368.          */
  4369.         gotocmdline(TRUE);
  4370.         for (i = 0; i < arg_file_count; ++i)
  4371.         {
  4372.         if (i == curwin->w_arg_idx)
  4373.             msg_putchar('[');
  4374.         msg_outtrans(arg_files[i]);
  4375.         if (i == curwin->w_arg_idx)
  4376.             msg_putchar(']');
  4377.         msg_putchar(' ');
  4378.         }
  4379.     }
  4380.     }
  4381. }
  4382.  
  4383. /*
  4384.  * Handle ":wnext", ":wNext" and ":wprevious" commands.
  4385.  */
  4386.     static void
  4387. do_wnext(eap)
  4388.     EXARG    *eap;
  4389. {
  4390.     int        i;
  4391.  
  4392.     if (eap->cmd[1] == 'n')
  4393.     i = curwin->w_arg_idx + (int)eap->line2;
  4394.     else
  4395.     i = curwin->w_arg_idx - (int)eap->line2;
  4396.     eap->line1 = 1;
  4397.     eap->line2 = curbuf->b_ml.ml_line_count;
  4398.     if (do_write(eap) != FAIL)
  4399.     do_argfile(eap, i);
  4400. }
  4401.  
  4402. /*
  4403.  * :sview [+command] file   split window with new file, read-only
  4404.  * :split [[+command] file] split window with current or new file
  4405.  * :new [[+command] file]   split window with no or new file
  4406.  */
  4407.     static void
  4408. do_splitview(eap)
  4409.     EXARG   *eap;
  4410. {
  4411.     WIN        *old_curwin;
  4412.  
  4413.     old_curwin = curwin;
  4414.     if (win_split(eap->addr_count ? (int)eap->line2 : 0, FALSE, FALSE) != FAIL)
  4415.     do_exedit(eap, old_curwin);
  4416. }
  4417.  
  4418. /*
  4419.  * Handle ":resize" command.
  4420.  * set, increment or decrement current window height
  4421.  */
  4422.     static void
  4423. do_resize(eap)
  4424.     EXARG    *eap;
  4425. {
  4426.     int        n;
  4427.  
  4428.     n = atol((char *)eap->arg);
  4429.     if (*eap->arg == '-' || *eap->arg == '+')
  4430.     n += curwin->w_height;
  4431.     else if (n == 0)        /* default is very high */
  4432.     n = 9999;
  4433.     win_setheight((int)n);
  4434. }
  4435.  
  4436.     static void
  4437. do_exedit(eap, old_curwin)
  4438.     EXARG    *eap;
  4439.     WIN        *old_curwin;
  4440. {
  4441.     int        n;
  4442.  
  4443.     /*
  4444.      * ":vi" command ends Ex mode.
  4445.      */
  4446.     if (eap->cmdidx == CMD_visual || eap->cmdidx == CMD_view)
  4447.     {
  4448.     exmode_active = FALSE;
  4449.     if (*eap->arg == NUL)
  4450.         return;
  4451.     }
  4452.  
  4453.     if ((eap->cmdidx == CMD_new) && *eap->arg == NUL)
  4454.     {
  4455.     setpcmark();
  4456.     (void)do_ecmd(0, NULL, NULL, eap->do_ecmd_cmd, (linenr_t)1,
  4457.                    ECMD_HIDE + (eap->forceit ? ECMD_FORCEIT : 0));
  4458.     }
  4459.     else if (eap->cmdidx != CMD_split || *eap->arg != NUL)
  4460.     {
  4461.     n = readonlymode;
  4462.     if (eap->cmdidx == CMD_view || eap->cmdidx == CMD_sview)
  4463.         readonlymode = TRUE;
  4464.     setpcmark();
  4465.     (void)do_ecmd(0, eap->arg, NULL, eap->do_ecmd_cmd, eap->do_ecmd_lnum,
  4466.                      (p_hid ? ECMD_HIDE : 0) +
  4467.                     (eap->forceit ? ECMD_FORCEIT : 0));
  4468.     readonlymode = n;
  4469.     }
  4470.     else
  4471.     {
  4472.     if (eap->do_ecmd_cmd != NULL)
  4473.         do_cmdline(eap->do_ecmd_cmd, NULL, NULL, DOCMD_VERBOSE);
  4474.     update_screen(NOT_VALID);
  4475.     }
  4476.  
  4477.     /*
  4478.      * if ":split file" worked, set alternate file name in old window to new
  4479.      * file
  4480.      */
  4481.     if (       (eap->cmdidx == CMD_new
  4482.         || eap->cmdidx == CMD_split)
  4483.         && *eap->arg != NUL
  4484.         && curwin != old_curwin
  4485.         && win_valid(old_curwin)
  4486.         && old_curwin->w_buffer != curbuf)
  4487.     old_curwin->w_alt_fnum = curbuf->b_fnum;
  4488.  
  4489.     ex_no_reprint = TRUE;
  4490. }
  4491.  
  4492. #ifdef USE_GUI
  4493. /*
  4494.  * Handle ":gui" or ":gvim" command.
  4495.  */
  4496.     static void
  4497. do_gui(eap)
  4498.     EXARG    *eap;
  4499. {
  4500.     /*
  4501.      * Check for "-f" argument: foreground, don't fork.
  4502.      */
  4503.     if (eap->arg[0] == '-' && eap->arg[1] == 'f' &&
  4504.                  (eap->arg[2] == NUL || vim_iswhite(eap->arg[2])))
  4505.     {
  4506.     gui.dofork = FALSE;
  4507.     eap->arg = skipwhite(eap->arg + 2);
  4508.     }
  4509.     else
  4510.     gui.dofork = TRUE;
  4511.     if (!gui.in_use)
  4512.     {
  4513.     /* Clear the command.  Needed for when forking+exiting, to avoid part
  4514.      * of the argument ending up after the shell prompt. */
  4515.     msg_clr_eos();
  4516.     gui_start();
  4517.     }
  4518.     if (!ends_excmd(*eap->arg))
  4519.     do_next(eap);
  4520. }
  4521. #endif
  4522.  
  4523.     static void
  4524. do_swapname()
  4525. {
  4526.     if (curbuf->b_ml.ml_mfp == NULL || curbuf->b_ml.ml_mfp->mf_fname == NULL)
  4527.     MSG("No swap file");
  4528.     else
  4529.     msg(curbuf->b_ml.ml_mfp->mf_fname);
  4530. }
  4531.  
  4532.     static void
  4533. do_read(eap)
  4534.     EXARG    *eap;
  4535. {
  4536.     int        i;
  4537.  
  4538.     if (eap->usefilter)            /* :r!cmd */
  4539.     do_bang(1, eap->line1, eap->line2, FALSE, eap->arg, FALSE, TRUE);
  4540.     else
  4541.     {
  4542.     if (u_save(eap->line2, (linenr_t)(eap->line2 + 1)) == FAIL)
  4543.         return;
  4544.  
  4545.     if (*eap->arg == NUL)
  4546.     {
  4547.         if (check_fname() == FAIL)    /* check for no file name */
  4548.         return;
  4549.         i = readfile(curbuf->b_ffname, curbuf->b_fname,
  4550.                    eap->line2, (linenr_t)0, (linenr_t)MAXLNUM, 0);
  4551.     }
  4552.     else
  4553.     {
  4554.         if (vim_strchr(p_cpo, CPO_ALTREAD) != NULL)
  4555.         setaltfname(eap->arg, eap->arg, (linenr_t)1);
  4556.         i = readfile(eap->arg, NULL,
  4557.                    eap->line2, (linenr_t)0, (linenr_t)MAXLNUM, 0);
  4558.  
  4559.     }
  4560.     if (i == FAIL)
  4561.         emsg2(e_notopen, eap->arg);
  4562.     else
  4563.         update_screen(NOT_VALID);
  4564.     }
  4565. }
  4566.  
  4567.     static void
  4568. do_cd(eap)
  4569.     EXARG    *eap;
  4570. {
  4571.     BUF        *buf;
  4572.     char_u    *p;
  4573.  
  4574. #ifdef UNIX
  4575.     /*
  4576.      * for UNIX ":cd" means: go to home directory
  4577.      */
  4578.     if (*eap->arg == NUL)    /* use NameBuff for home directory name */
  4579.     {
  4580.     expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
  4581.     eap->arg = NameBuff;
  4582.     }
  4583. #endif
  4584.     if (*eap->arg == NUL)
  4585.     do_pwd();
  4586.     else
  4587.     {
  4588.     if (vim_chdir((char *)eap->arg))
  4589.         emsg(e_failed);
  4590.     else
  4591.     {
  4592.         /*
  4593.          * Use full path from now on for files currently being
  4594.          * edited, both for file name and swap file name.  Try
  4595.          * to shorten the file names a bit if safe to do so.
  4596.          */
  4597.         mch_dirname(IObuff, IOSIZE);
  4598.         for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  4599.         {
  4600.         if (buf->b_fname != NULL)
  4601.         {
  4602.             vim_free(buf->b_sfname);
  4603.             buf->b_sfname = NULL;
  4604.             p = shorten_fname(buf->b_ffname, IObuff);
  4605.             if (p != NULL)
  4606.             {
  4607.             buf->b_sfname = vim_strsave(p);
  4608.             buf->b_fname = buf->b_sfname;
  4609.             }
  4610.             if (p == NULL || buf->b_fname == NULL)
  4611.             buf->b_fname = buf->b_ffname;
  4612.             mf_fullname(buf->b_ml.ml_mfp);
  4613.         }
  4614.         }
  4615.         status_redraw_all();
  4616.     }
  4617.     }
  4618. }
  4619.  
  4620.     static void
  4621. do_pwd()
  4622. {
  4623.     if (mch_dirname(NameBuff, MAXPATHL) == OK)
  4624.     msg(NameBuff);
  4625.     else
  4626.     emsg(e_unknown);
  4627. }
  4628.  
  4629.     static void
  4630. do_sleep(eap)
  4631.     EXARG    *eap;
  4632. {
  4633.     int        n;
  4634.  
  4635.     if (cursor_valid())
  4636.     {
  4637.     n = curwin->w_winpos + curwin->w_wrow - msg_scrolled;
  4638.     if (n >= 0)
  4639.     {
  4640.         windgoto((int)n, curwin->w_wcol);
  4641.         out_flush();
  4642.     }
  4643.     }
  4644.     ui_delay(eap->line2 * 1000L, TRUE);
  4645. }
  4646.  
  4647.     static void
  4648. do_exmap(eap, isabbrev)
  4649.     EXARG    *eap;
  4650.     int        isabbrev;
  4651. {
  4652.     int        mode;
  4653.     char_u  *cmdp;
  4654.  
  4655.     cmdp = eap->cmd;
  4656.     mode = get_map_mode(&cmdp, eap->forceit || isabbrev);
  4657.  
  4658.     switch (do_map((*cmdp == 'n') ? 2 : (*cmdp == 'u'),
  4659.                             eap->arg, mode, isabbrev))
  4660.     {
  4661.     case 1: emsg(e_invarg);
  4662.         break;
  4663.     case 2: emsg(e_nomap);
  4664.         break;
  4665.     case 3: emsg(e_ambmap);
  4666.         break;
  4667.     }
  4668. }
  4669.  
  4670. /*
  4671.  * ":winsize" command (obsolete).
  4672.  */
  4673.     static void
  4674. do_winsize(arg)
  4675.     char_u    *arg;
  4676. {
  4677.     int        w, h;
  4678.  
  4679.     w = getdigits(&arg);
  4680.     arg = skipwhite(arg);
  4681.     h = getdigits(&arg);
  4682.     set_winsize(w, h, TRUE);
  4683. }
  4684.  
  4685. /*
  4686.  * Handle command that work like operators: ":delete", ":yank", ":>" and ":<".
  4687.  */
  4688.     static void
  4689. do_exops(eap)
  4690.     EXARG    *eap;
  4691. {
  4692.     OPARG    oa;
  4693.  
  4694.     clear_oparg(&oa);
  4695.     oa.regname = eap->regname;
  4696.     oa.start.lnum = eap->line1;
  4697.     oa.end.lnum = eap->line2;
  4698.     oa.line_count = eap->line2 - eap->line1 + 1;
  4699.     oa.motion_type = MLINE;
  4700.     if (eap->cmdidx != CMD_yank)    /* position cursor for undo */
  4701.     {
  4702.     setpcmark();
  4703.     curwin->w_cursor.lnum = eap->line1;
  4704.     beginline(BL_SOL | BL_FIX);
  4705.     }
  4706.  
  4707.     switch (eap->cmdidx)
  4708.     {
  4709.     case CMD_delete:
  4710.         oa.op_type = OP_DELETE;
  4711.         op_delete(&oa);
  4712.         break;
  4713.  
  4714.     case CMD_yank:
  4715.         oa.op_type = OP_YANK;
  4716.         (void)op_yank(&oa, FALSE, TRUE);
  4717.         break;
  4718.  
  4719.     default:    /* CMD_rshift or CMD_lshift */
  4720.         if ((eap->cmdidx == CMD_rshift)
  4721. #ifdef RIGHTLEFT
  4722.                     ^ curwin->w_p_rl
  4723. #endif
  4724.                             )
  4725.         oa.op_type = OP_RSHIFT;
  4726.         else
  4727.         oa.op_type = OP_LSHIFT;
  4728.         op_shift(&oa, FALSE, eap->amount);
  4729.         break;
  4730.     }
  4731. }
  4732.  
  4733. /*
  4734.  * Handle ":copy" and ":move".
  4735.  */
  4736.     static void
  4737. do_copymove(eap)
  4738.     EXARG    *eap;
  4739. {
  4740.     long    n;
  4741.  
  4742.     n = get_address(&eap->arg);
  4743.     if (eap->arg == NULL)        /* error detected */
  4744.     {
  4745.     eap->nextcmd = NULL;
  4746.     return;
  4747.     }
  4748.  
  4749.     /*
  4750.      * move or copy lines from 'eap->line1'-'eap->line2' to below line 'n'
  4751.      */
  4752.     if (n == MAXLNUM || n < 0 || n > curbuf->b_ml.ml_line_count)
  4753.     {
  4754.     emsg(e_invaddr);
  4755.     return;
  4756.     }
  4757.  
  4758.     if (eap->cmdidx == CMD_move)
  4759.     {
  4760.     if (do_move(eap->line1, eap->line2, n) == FAIL)
  4761.         return;
  4762.     }
  4763.     else
  4764.     do_copy(eap->line1, eap->line2, n);
  4765.     u_clearline();
  4766.     beginline(BL_SOL | BL_FIX);
  4767.     update_screen(NOT_VALID);
  4768. }
  4769.  
  4770. /*
  4771.  * Handle ":join" command.
  4772.  */
  4773.     static void
  4774. do_exjoin(eap)
  4775.     EXARG    *eap;
  4776. {
  4777.     curwin->w_cursor.lnum = eap->line1;
  4778.     if (eap->line1 == eap->line2)
  4779.     {
  4780.     if (eap->addr_count >= 2)   /* :2,2join does nothing */
  4781.         return;
  4782.     if (eap->line2 == curbuf->b_ml.ml_line_count)
  4783.     {
  4784.         beep_flush();
  4785.         return;
  4786.     }
  4787.     ++eap->line2;
  4788.     }
  4789.     do_do_join(eap->line2 - eap->line1 + 1, !eap->forceit, FALSE);
  4790.     beginline(BL_WHITE | BL_FIX);
  4791. }
  4792.  
  4793. /*
  4794.  * Handle ":@" command, execute from register.
  4795.  */
  4796.     static void
  4797. do_exat(eap)
  4798.     EXARG    *eap;
  4799. {
  4800.     curwin->w_cursor.lnum = eap->line2;
  4801.  
  4802. #ifdef USE_GUI_WIN32
  4803.     dont_scroll = TRUE;        /* disallow scrolling here */
  4804. #endif
  4805.  
  4806.     /* put the register in mapbuf */
  4807.     if (do_execreg(*eap->arg, TRUE,
  4808.                   vim_strchr(p_cpo, CPO_EXECBUF) != NULL) == FAIL)
  4809.     beep_flush();
  4810.     else
  4811.     {
  4812.     /* execute from the mapbuf */
  4813.     while (vpeekc() == ':')
  4814.     {
  4815.         (void)vgetc();
  4816.         (void)do_cmdline(NULL, getexline, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE);
  4817.     }
  4818.     }
  4819. }
  4820.  
  4821. /*
  4822.  * Handle ":redir" command, start/stop redirection.
  4823.  */
  4824.     static void
  4825. do_redir(eap)
  4826.     EXARG    *eap;
  4827. {
  4828.     char    *mode;
  4829.  
  4830.     if (STRICMP(eap->arg, "END") == 0)
  4831.     close_redir();
  4832.     else
  4833.     {
  4834.     if (*eap->arg == '>')
  4835.     {
  4836.         ++eap->arg;
  4837.         if (*eap->arg == '>')
  4838.         {
  4839.         ++eap->arg;
  4840.         mode = "a";
  4841.         }
  4842.         else
  4843.         mode = "w";
  4844.         eap->arg = skipwhite(eap->arg);
  4845.  
  4846.         close_redir();
  4847.         redir_fd = open_exfile(eap, mode);
  4848.     }
  4849.  
  4850.     /* TODO: redirect to a buffer */
  4851.  
  4852.     /* TODO: redirect to an internal variable */
  4853.  
  4854.     else
  4855.         EMSG(e_invarg);
  4856.     }
  4857. }
  4858.  
  4859.     static void
  4860. close_redir()
  4861. {
  4862.     if (redir_fd != NULL)
  4863.     {
  4864.     fclose(redir_fd);
  4865.     redir_fd = NULL;
  4866.     }
  4867. }
  4868.  
  4869. /*
  4870.  * Handle ":mkexrc" and ":mkvimrc" commands.
  4871.  */
  4872.     static void
  4873. do_mkrc(eap)
  4874.     EXARG    *eap;
  4875. {
  4876.     FILE    *fd;
  4877.  
  4878.     if (*eap->arg == NUL)
  4879.     eap->arg = (char_u *)EXRC_FILE;
  4880.     fd = open_exfile(eap, WRITEBIN);
  4881.     if (fd == NULL)
  4882.     return;
  4883.  
  4884.     /* Write the version command for :mkvimrc */
  4885.     if (eap->cmdidx == CMD_mkvimrc)
  4886.     {
  4887. #ifdef USE_CRNL
  4888.     fprintf(fd, "version 5.0\r\n");
  4889. #else
  4890.     fprintf(fd, "version 5.0\n");
  4891. #endif
  4892.     }
  4893.  
  4894.     if (makemap(fd) == FAIL || makeset(fd) == FAIL || fclose(fd))
  4895.     emsg(e_write);
  4896. }
  4897.  
  4898. /*
  4899.  * Open a file for writing for an Ex command, with some checks.
  4900.  * Return file descriptor, or NULL on failure.
  4901.  */
  4902.     static FILE    *
  4903. open_exfile(eap, mode)
  4904.     EXARG    *eap;
  4905.     char    *mode;        /* "w" for create new file or "a" for append */
  4906. {
  4907.     FILE    *fd;
  4908.  
  4909. #ifdef UNIX
  4910.     /* with Unix it is possible to open a directory */
  4911.     if (mch_isdir(eap->arg))
  4912.     {
  4913.     EMSG2("\"%s\" is a directory", eap->arg);
  4914.     return NULL;
  4915.     }
  4916. #endif
  4917.     if (!eap->forceit && *mode != 'a' && vim_fexists(eap->arg))
  4918.     {
  4919.     EMSG2("\"%s\" exists (use ! to override)", eap->arg);
  4920.     return NULL;
  4921.     }
  4922.  
  4923.     if ((fd = fopen((char *)eap->arg, mode)) == NULL)
  4924.     {
  4925.     EMSG2("Cannot open \"%s\" for writing", eap->arg);
  4926.     return NULL;
  4927.     }
  4928.     return fd;
  4929. }
  4930.  
  4931. /*
  4932.  * Handle ":mark" or ":k" command.
  4933.  */
  4934.     static void
  4935. do_setmark(eap)
  4936.     EXARG    *eap;
  4937. {
  4938.     FPOS    pos;
  4939.  
  4940.     pos = curwin->w_cursor;        /* save curwin->w_cursor */
  4941.     curwin->w_cursor.lnum = eap->line2;
  4942.     beginline(BL_WHITE | BL_FIX);
  4943.     (void)setmark(*eap->arg);        /* set mark */
  4944.     curwin->w_cursor = pos;        /* restore curwin->w_cursor */
  4945. }
  4946.  
  4947. #ifdef EX_EXTRA
  4948. /*
  4949.  * Handle ":normal[!] {commands}" - execute normal mode commands
  4950.  * Often used for ":autocmd".
  4951.  */
  4952.     static void
  4953. do_normal(eap)
  4954.     EXARG    *eap;
  4955. {
  4956.     OPARG    oa;
  4957.     int        len;
  4958.     int        save_msg_scroll = msg_scroll;
  4959.     int        save_restart_edit = restart_edit;
  4960.     int        save_msg_didout = msg_didout;
  4961.  
  4962.     msg_scroll = FALSE;        /* no msg scrolling in Normal mode */
  4963.     restart_edit = 0;        /* don't go to Insert mode */
  4964.  
  4965.     /*
  4966.      * Repeat the :normal command for each line in the range.  When no range
  4967.      * given, execute it just once, without positioning the cursor first.
  4968.      */
  4969.     do
  4970.     {
  4971.     clear_oparg(&oa);
  4972.     if (eap->addr_count != 0)
  4973.     {
  4974.         curwin->w_cursor.lnum = eap->line1++;
  4975.         curwin->w_cursor.col = 0;
  4976.     }
  4977.  
  4978.     /*
  4979.      * Stuff the argument into the typeahead buffer.
  4980.      * Execute normal_cmd() until there is no more
  4981.      * typeahead than there was before this command.
  4982.      */
  4983.     len = typelen;
  4984.     ins_typebuf(eap->arg, eap->forceit ? -1 : 0, 0, TRUE);
  4985.     while (       (!stuff_empty()
  4986.             || (!typebuf_typed()
  4987.                 && typelen > len))
  4988.         && !got_int)
  4989.     {
  4990.         adjust_cursor();        /* put cursor on valid line */
  4991.         /* Make sure w_topline and w_leftcol are correct. */
  4992.         update_topline();
  4993.         if (!curwin->w_p_wrap)
  4994.         validate_cursor();
  4995.         update_curswant();
  4996.  
  4997.         normal_cmd(&oa, FALSE);    /* execute a Normal mode cmd */
  4998.     }
  4999.     }
  5000.     while (eap->addr_count > 0 && eap->line1 <= eap->line2 && !got_int);
  5001.  
  5002.     msg_scroll = save_msg_scroll;
  5003.     restart_edit = save_restart_edit;
  5004.     msg_didout |= save_msg_didout;    /* don't reset msg_didout now */
  5005. }
  5006. #endif
  5007.  
  5008. #ifdef FIND_IN_PATH
  5009.     static char_u *
  5010. do_findpat(eap, action)
  5011.     EXARG    *eap;
  5012.     int        action;
  5013. {
  5014.     int        whole = TRUE;
  5015.     long    n;
  5016.     char_u    *p;
  5017.     char_u    *errormsg = NULL;
  5018.  
  5019.     n = 1;
  5020.     if (isdigit(*eap->arg))    /* get count */
  5021.     {
  5022.     n = getdigits(&eap->arg);
  5023.     eap->arg = skipwhite(eap->arg);
  5024.     }
  5025.     if (*eap->arg == '/')   /* Match regexp, not just whole words */
  5026.     {
  5027.     whole = FALSE;
  5028.     ++eap->arg;
  5029.     p = skip_regexp(eap->arg, '/', p_magic);
  5030.     if (*p)
  5031.     {
  5032.         *p++ = NUL;
  5033.         p = skipwhite(p);
  5034.  
  5035.         /* Check for trailing illegal characters */
  5036.         if (!ends_excmd(*p))
  5037.         errormsg = e_trailing;
  5038.         else
  5039.         eap->nextcmd = check_nextcmd(p);
  5040.     }
  5041.     }
  5042.     if (!eap->skip)
  5043.     find_pattern_in_path(eap->arg, 0, (int)STRLEN(eap->arg),
  5044.                 whole, !eap->forceit,
  5045.                 *eap->cmd == 'd' ?    FIND_DEFINE : FIND_ANY,
  5046.                 n, action, eap->line1, eap->line2);
  5047.  
  5048.     return errormsg;
  5049. }
  5050. #endif
  5051.  
  5052.     static void
  5053. do_ex_tag(eap, dt)
  5054.     EXARG    *eap;
  5055.     int        dt;
  5056. {
  5057.     do_tag((char_u *)"", dt, eap->addr_count ? (int)eap->line2
  5058.                          : 1, eap->forceit);
  5059. }
  5060.  
  5061. #ifdef WANT_EVAL
  5062.  
  5063.     static char_u *
  5064. do_if(eap, cstack)
  5065.     EXARG        *eap;
  5066.     struct condstack    *cstack;
  5067. {
  5068.     char_u    *errormsg = NULL;
  5069.     int        error;
  5070.     int        skip;
  5071.     int        result;
  5072.  
  5073.     if (cstack->cs_idx == CSTACK_LEN - 1)
  5074.     errormsg = (char_u *)":if nesting too deep";
  5075.     else
  5076.     {
  5077.     ++cstack->cs_idx;
  5078.     cstack->cs_flags[cstack->cs_idx] = 0;
  5079.  
  5080.     /*
  5081.      * Don't do something when there is a surrounding conditional and it
  5082.      * was not active.
  5083.      */
  5084.     skip = (cstack->cs_idx > 0
  5085.         && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
  5086.     if (skip)
  5087.         ++emsg_off;
  5088.     result = eval_to_bool(eap->arg, &error, &eap->nextcmd);
  5089.     if (skip)
  5090.         --emsg_off;
  5091.  
  5092.     if (!skip)
  5093.     {
  5094.         if (result)
  5095.         cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE | CSF_TRUE;
  5096.         if (error)
  5097.         --cstack->cs_idx;
  5098.     }
  5099.     }
  5100.  
  5101.     return errormsg;
  5102. }
  5103.  
  5104. /*
  5105.  * Handle ":else" and ":elseif" commands.
  5106.  */
  5107.     static char_u *
  5108. do_else(eap, cstack)
  5109.     EXARG        *eap;
  5110.     struct condstack    *cstack;
  5111. {
  5112.     char_u    *errormsg = NULL;
  5113.     int        error;
  5114.     int        skip;
  5115.     int        result = FALSE;
  5116.  
  5117.     if (cstack->cs_idx < 0 || (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE))
  5118.     {
  5119.     if (eap->cmdidx == CMD_else)
  5120.         errormsg = (char_u *)":else without :if";
  5121.     else
  5122.         errormsg = (char_u *)":elseif without :if";
  5123.     }
  5124.     else
  5125.     {
  5126.     /*
  5127.      * Don't do something when there is a surrounding conditional and it
  5128.      * was not active.
  5129.      */
  5130.     skip = (cstack->cs_idx > 0
  5131.         && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
  5132.     if (!skip)
  5133.     {
  5134.         /* if the ":if" was TRUE, reset active, otherwise set it */
  5135.         if (cstack->cs_flags[cstack->cs_idx] & CSF_TRUE)
  5136.         cstack->cs_flags[cstack->cs_idx] = CSF_TRUE;
  5137.         else
  5138.         cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE;
  5139.     }
  5140.  
  5141.     if (eap->cmdidx == CMD_elseif)
  5142.     {
  5143.         if (skip)
  5144.         ++emsg_off;
  5145.         result = eval_to_bool(eap->arg, &error, &eap->nextcmd);
  5146.         if (skip)
  5147.         --emsg_off;
  5148.  
  5149.         if (!skip && (cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE))
  5150.         {
  5151.         if (result)
  5152.             cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE | CSF_TRUE;
  5153.         else
  5154.             cstack->cs_flags[cstack->cs_idx] = 0;
  5155.         if (error)
  5156.             --cstack->cs_idx;
  5157.         }
  5158.     }
  5159.     }
  5160.  
  5161.     return errormsg;
  5162. }
  5163.  
  5164. /*
  5165.  * Handle ":while".
  5166.  */
  5167.     static char_u *
  5168. do_while(eap, cstack)
  5169.     EXARG        *eap;
  5170.     struct condstack    *cstack;
  5171. {
  5172.     char_u    *errormsg = NULL;
  5173.     int        error;
  5174.     int        skip;
  5175.     int        result;
  5176.  
  5177.     if (cstack->cs_idx == CSTACK_LEN - 1)
  5178.     errormsg = (char_u *)":while nesting too deep";
  5179.     else
  5180.     {
  5181.     /*
  5182.      * cs_had_while is set when we have jumped back from the matching
  5183.      * ":endwhile".  When not set, need to init this cstack entry.
  5184.      */
  5185.     if (!cstack->cs_had_while)
  5186.     {
  5187.         ++cstack->cs_idx;
  5188.         ++cstack->cs_whilelevel;
  5189.     }
  5190.     cstack->cs_flags[cstack->cs_idx] = CSF_WHILE;
  5191.  
  5192.     /*
  5193.      * Don't do something when there is a surrounding conditional and it
  5194.      * was not active.
  5195.      */
  5196.     skip = (cstack->cs_idx > 0
  5197.         && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
  5198.     if (skip)
  5199.         ++emsg_off;
  5200.     result = eval_to_bool(eap->arg, &error, &eap->nextcmd);
  5201.     if (skip)
  5202.         --emsg_off;
  5203.  
  5204.     if (!skip)
  5205.     {
  5206.         if (result)
  5207.         cstack->cs_flags[cstack->cs_idx] |= CSF_ACTIVE | CSF_TRUE;
  5208.         if (error)
  5209.         --cstack->cs_idx;
  5210.         else
  5211.         /*
  5212.          * Set cs_had_while flag, so do_cmdline() will set the line
  5213.          * number in cs_line[].
  5214.          */
  5215.         cstack->cs_had_while = TRUE;
  5216.     }
  5217.     }
  5218.  
  5219.     return errormsg;
  5220. }
  5221.  
  5222. /*
  5223.  * Handle ":continue".
  5224.  */
  5225.     static char_u *
  5226. do_continue(cstack)
  5227.     struct condstack    *cstack;
  5228. {
  5229.     char_u    *errormsg = NULL;
  5230.  
  5231.     if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0)
  5232.     errormsg = (char_u *)":continue without :while";
  5233.     else
  5234.     {
  5235.     /* Find the matching ":while". */
  5236.     while (cstack->cs_idx > 0
  5237.             && !(cstack->cs_flags[cstack->cs_idx] & CSF_WHILE))
  5238.         --cstack->cs_idx;
  5239.  
  5240.     /*
  5241.      * Set cs_had_continue, so do_cmdline() will jump back to the matching
  5242.      * ":while".
  5243.      */
  5244.     cstack->cs_had_continue = TRUE;        /* let do_cmdline() handle it */
  5245.     }
  5246.  
  5247.     return errormsg;
  5248. }
  5249.  
  5250. /*
  5251.  * Handle ":break".
  5252.  */
  5253.     static char_u *
  5254. do_break(cstack)
  5255.     struct condstack    *cstack;
  5256. {
  5257.     char_u    *errormsg = NULL;
  5258.     int        idx;
  5259.  
  5260.     if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0)
  5261.     errormsg = (char_u *)":break without :while";
  5262.     else
  5263.     {
  5264.     /* Find the matching ":while". */
  5265.     for (idx = cstack->cs_idx; idx >= 0; --idx)
  5266.     {
  5267.         cstack->cs_flags[idx] &= ~CSF_ACTIVE;
  5268.         if (cstack->cs_flags[idx] & CSF_WHILE)
  5269.         break;
  5270.     }
  5271.     }
  5272.  
  5273.     return errormsg;
  5274. }
  5275.  
  5276. /*
  5277.  * Handle ":endwhile".
  5278.  */
  5279.     static char_u *
  5280. do_endwhile(cstack)
  5281.     struct condstack    *cstack;
  5282. {
  5283.     char_u    *errormsg = NULL;
  5284.  
  5285.     if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0)
  5286.     errormsg = (char_u *)":endwhile without :while";
  5287.     else
  5288.     {
  5289.     if (!(cstack->cs_flags[cstack->cs_idx] & CSF_WHILE))
  5290.     {
  5291.         errormsg = (char_u *)":enwhile without :while";
  5292.         while (cstack->cs_idx > 0
  5293.             && !(cstack->cs_flags[cstack->cs_idx] & CSF_WHILE))
  5294.         --cstack->cs_idx;
  5295.     }
  5296.     /*
  5297.      * Set cs_had_endwhile, so do_cmdline() will jump back to the matching
  5298.      * ":while".
  5299.      */
  5300.     cstack->cs_had_endwhile = TRUE;
  5301.     }
  5302.  
  5303.     return errormsg;
  5304. }
  5305.  
  5306. /*
  5307.  * Return TRUE if the string "p" looks like a ":while" command.
  5308.  */
  5309.     static int
  5310. has_while_cmd(p)
  5311.     char_u    *p;
  5312. {
  5313.     p = skipwhite(p);
  5314.     while (*p == ':')
  5315.     ++p;
  5316.     p = skipwhite(p);
  5317.     if (p[0] == 'w' && p[1] == 'h')
  5318.     return TRUE;
  5319.     return FALSE;
  5320. }
  5321.  
  5322. #endif /* WANT_EVAL */
  5323.  
  5324. /*
  5325.  * Evaluate cmdline variables.
  5326.  *
  5327.  * change '%'        to curbuf->b_ffname
  5328.  *      '#'        to curwin->w_altfile
  5329.  *      '<cword>' to word under the cursor
  5330.  *      '<cWORD>' to WORD under the cursor
  5331.  *      '<cfile>' to path name under the cursor
  5332.  *      '<sfile>" to sourced file name
  5333.  *      '<afile>' to file name for autocommand
  5334.  *
  5335.  * When an error is detected, "errormsg" is set to a non-NULL pointer (may be
  5336.  * "" for error without a message) and NULL is returned.
  5337.  * Returns an allocated string if a valid match was found.
  5338.  * Returns NULL if no match was found.    "usedlen" then still contains the
  5339.  * number of characters to skip.
  5340.  */
  5341.     char_u *
  5342. eval_vars(src, usedlen, lnump, errormsg)
  5343.     char_u    *src;        /* pointer into commandline */
  5344.     int        *usedlen;    /* characters after src that are used */
  5345.     linenr_t    *lnump;        /* line number for :e command, or NULL */
  5346.     char_u    **errormsg;    /* error message, or NULL */
  5347. {
  5348.     int        i;
  5349.     char_u    *s;
  5350.     char_u    *tail;
  5351.     char_u    *result;
  5352.     int        resultlen;
  5353.     char_u    *buf = NULL;
  5354.     BUF        *buffer;
  5355. #define VALID_P        1
  5356. #define VALID_H        2
  5357.     int        valid = VALID_H + VALID_P;    /* assume valid result */
  5358.     int        spec_idx;
  5359.     static char *(spec_str[]) =
  5360.         {
  5361.             "%",
  5362. #define SPEC_PERC   0
  5363.             "#",
  5364. #define SPEC_HASH   1
  5365.             "<cword>",        /* cursor word */
  5366. #define SPEC_CWORD  2
  5367.             "<cWORD>",        /* cursor WORD */
  5368. #define SPEC_CCWORD 3
  5369.             "<cfile>",        /* cursor path name */
  5370. #define SPEC_CFILE  4
  5371.             "<sfile>",        /* ":so" file name */
  5372. #define SPEC_SFILE  5
  5373. #ifdef AUTOCMD
  5374.             "<afile>"        /* autocommand file name */
  5375. # define SPEC_AFILE 6
  5376. #endif
  5377.         };
  5378. #define SPEC_COUNT  (sizeof(spec_str) / sizeof(char *))
  5379.  
  5380.     *errormsg = NULL;
  5381.  
  5382.     /*
  5383.      * Check if there is something to do.
  5384.      */
  5385.     for (spec_idx = 0; spec_idx < SPEC_COUNT; ++spec_idx)
  5386.     {
  5387.     *usedlen = strlen(spec_str[spec_idx]);
  5388.     if (STRNCMP(src, spec_str[spec_idx], *usedlen) == 0)
  5389.         break;
  5390.     }
  5391.     if (spec_idx == SPEC_COUNT)        /* no match */
  5392.     {
  5393.     *usedlen = 1;
  5394.     return NULL;
  5395.     }
  5396.  
  5397.     /*
  5398.      * Skip when preceded with a backslash "\%" and "\#".
  5399.      * Note: In "\\%" the % is also not recognized!
  5400.      */
  5401.     if (*(src - 1) == '\\')
  5402.     {
  5403.     *usedlen = 0;
  5404.     STRCPY(src - 1, src);        /* remove backslash */
  5405.     return NULL;
  5406.     }
  5407.  
  5408.     /*
  5409.      * word or WORD under cursor
  5410.      */
  5411.     if (spec_idx == SPEC_CWORD || spec_idx == SPEC_CCWORD)
  5412.     {
  5413.     resultlen = find_ident_under_cursor(&result, spec_idx == SPEC_CWORD ?
  5414.                       (FIND_IDENT|FIND_STRING) : FIND_STRING);
  5415.     if (resultlen == 0)
  5416.     {
  5417.         *errormsg = (char_u *)"";
  5418.         return NULL;
  5419.     }
  5420.     }
  5421.  
  5422.     /*
  5423.      * '#': Alternate file name
  5424.      * '%': Current file name
  5425.      *        File name under the cursor
  5426.      *        File name for autocommand
  5427.      *    and following modifiers
  5428.      */
  5429.     else
  5430.     {
  5431.     switch (spec_idx)
  5432.     {
  5433.     case SPEC_PERC:            /* '%': current file */
  5434.         if (curbuf->b_fname == NULL)
  5435.         {
  5436.             result = (char_u *)"";
  5437.             valid = 0;        /* Must have ":p:h" to be valid */
  5438.         }
  5439.         else
  5440.             result = curbuf->b_fname;
  5441.         break;
  5442.  
  5443.     case SPEC_HASH:        /* '#' or "#99": alternate file */
  5444.         s = src + 1;
  5445.         i = (int)getdigits(&s);
  5446.         *usedlen = s - src;    /* length of what we expand */
  5447.  
  5448.         buffer = buflist_findnr(i);
  5449.         if (buffer == NULL)
  5450.         {
  5451.             *errormsg = (char_u *)"No alternate file name to substitute for '#'";
  5452.             return NULL;
  5453.         }
  5454.         if (lnump != NULL)
  5455.             *lnump = buflist_findlnum(buffer);
  5456.         if (buffer->b_fname == NULL)
  5457.         {
  5458.             result = (char_u *)"";
  5459.             valid = 0;        /* Must have ":p:h" to be valid */
  5460.         }
  5461.         else
  5462.             result = buffer->b_fname;
  5463.         break;
  5464.  
  5465. #ifdef FILE_IN_PATH
  5466.     case SPEC_CFILE:        /* file name under cursor */
  5467.         result = file_name_at_cursor(FNAME_MESS|FNAME_HYP, 1L);
  5468.         if (result == NULL)
  5469.         {
  5470.             *errormsg = (char_u *)"";
  5471.             return NULL;
  5472.         }
  5473.         buf = result;        /* remember allocated string */
  5474.         break;
  5475. #endif
  5476.  
  5477. #ifdef AUTOCMD
  5478.     case SPEC_AFILE:        /* file name for autocommand */
  5479.         result = autocmd_fname;
  5480.         if (result == NULL)
  5481.         {
  5482.             *errormsg = (char_u *)"no autocommand file name to substitute for \"<afile>\"";
  5483.             return NULL;
  5484.         }
  5485.         break;
  5486. #endif
  5487.     case SPEC_SFILE:        /* file name for ":so" command */
  5488.         result = sourcing_name;
  5489.         if (result == NULL)
  5490.         {
  5491.             *errormsg = (char_u *)"no :soure file name to substitute for \"<sfile>\"";
  5492.             return NULL;
  5493.         }
  5494.         break;
  5495.     }
  5496.  
  5497.     resultlen = STRLEN(result);    /* length of new string */
  5498.     if (src[*usedlen] == '<')    /* remove the file name extension */
  5499.     {
  5500.         ++*usedlen;
  5501.         if ((s = vim_strrchr(result, '.')) != NULL && s >= gettail(result))
  5502.         resultlen = s - result;
  5503.     }
  5504.     else
  5505.     {
  5506.         /* ":p" - full path/file_name */
  5507.         if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
  5508.         {
  5509.         valid |= VALID_P;
  5510.         *usedlen += 2;
  5511.         result = FullName_save(result, FALSE);
  5512.         vim_free(buf);        /* free any allocated file name */
  5513.         if (result == NULL)
  5514.         {
  5515.             *errormsg = (char_u *)"";
  5516.             return NULL;
  5517.         }
  5518.         resultlen = STRLEN(result);
  5519.         buf = result;
  5520.         }
  5521.  
  5522.         tail = gettail(result);
  5523.  
  5524.         /* ":h" - head, remove "/file_name", can be repeated  */
  5525.         /* Don't remove the first "/" or "c:\" */
  5526.         while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
  5527.         {
  5528.         valid |= VALID_H;
  5529.         *usedlen += 2;
  5530.         s = get_past_head(result);
  5531.         while (tail > s && vim_ispathsep(tail[-1]))
  5532.             --tail;
  5533.         resultlen = tail - result;
  5534.         while (tail > s && !vim_ispathsep(tail[-1]))
  5535.             --tail;
  5536.         }
  5537.  
  5538.         /* ":t" - tail, just the basename */
  5539.         if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
  5540.         {
  5541.         *usedlen += 2;
  5542.         resultlen -= tail - result;
  5543.         result = tail;
  5544.         }
  5545.  
  5546.         /* ":e" - extension, can be repeated */
  5547.         /* ":r" - root, without extension, can be repeated */
  5548.         while (src[*usedlen] == ':' &&
  5549.                (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
  5550.         {
  5551.         /* find a '.' in the tail:
  5552.          * - for second :e: before the current fname
  5553.          * - otherwise: The last '.'
  5554.          */
  5555.         if (src[*usedlen + 1] == 'e' && result > tail)
  5556.             s = result - 2;
  5557.         else
  5558.             s = result + resultlen - 1;
  5559.         for ( ; s > tail; --s)
  5560.             if (s[0] == '.')
  5561.             break;
  5562.         if (src[*usedlen + 1] == 'e')        /* :e */
  5563.         {
  5564.             if (s > tail)
  5565.             {
  5566.             resultlen += result - (s + 1);
  5567.             result = s + 1;
  5568.             }
  5569.             else if (result <= tail)
  5570.             resultlen = 0;
  5571.         }
  5572.         else                /* :r */
  5573.         {
  5574.             if (s > tail)    /* remove one extension */
  5575.             resultlen = s - result;
  5576.         }
  5577.         *usedlen += 2;
  5578.         }
  5579.     }
  5580.  
  5581.     /* TODO - ":s/pat/foo/" - substitute */
  5582.     /* if (src[*usedlen] == ':' && src[*usedlen + 1] == 's') */
  5583.     }
  5584.  
  5585.     if (resultlen == 0 || valid != VALID_H + VALID_P)
  5586.     {
  5587.     if (valid != VALID_H + VALID_P)
  5588.         *errormsg = (char_u *)"Empty file name for '%' or '#', only works with \":p:h\"";
  5589.     else
  5590.         *errormsg = (char_u *)"Evaluates to an empty string";
  5591.     result = NULL;
  5592.     }
  5593.     else
  5594.     result = vim_strnsave(result, resultlen);
  5595.     vim_free(buf);
  5596.     return result;
  5597. }
  5598.  
  5599. /*
  5600.  * Expand the <sfile> string in "arg".
  5601.  *
  5602.  * Returns an allocated string, or NULL for any error.
  5603.  */
  5604.     char_u *
  5605. expand_sfile(arg)
  5606.     char_u    *arg;
  5607. {
  5608.     char_u    *errormsg;
  5609.     int        len;
  5610.     char_u    *result;
  5611.     char_u    *newres;
  5612.     char_u    *repl;
  5613.     int        srclen;
  5614.     char_u    *p;
  5615.     linenr_t    dummy;
  5616.  
  5617.     result = vim_strsave(arg);
  5618.     if (result == NULL)
  5619.     return NULL;
  5620.  
  5621.     for (p = result; *p; )
  5622.     {
  5623.     if (STRNCMP(p, "<sfile>", 7))
  5624.         ++p;
  5625.     else
  5626.     {
  5627.         /* replace "<sfile>" with the sourced file name, and do ":" stuff */
  5628.         repl = eval_vars(p, &srclen, &dummy, &errormsg);
  5629.         if (errormsg != NULL)
  5630.         {
  5631.         if (*errormsg)
  5632.             emsg(errormsg);
  5633.         vim_free(result);
  5634.         return NULL;
  5635.         }
  5636.         if (repl == NULL)        /* no match (cannot happen) */
  5637.         {
  5638.         p += srclen;
  5639.         continue;
  5640.         }
  5641.         len = STRLEN(result) - srclen + STRLEN(repl) + 1;
  5642.         newres = alloc(len);
  5643.         if (newres == NULL)
  5644.         {
  5645.         vim_free(repl);
  5646.         vim_free(result);
  5647.         return NULL;
  5648.         }
  5649.         vim_memmove(newres, result, (size_t)(p - result));
  5650.         STRCPY(newres + (p - result), repl);
  5651.         len = STRLEN(newres);
  5652.         STRCAT(newres, p + srclen);
  5653.         vim_free(result);
  5654.         result = newres;
  5655.         p = newres + len;        /* continue after the match */
  5656.     }
  5657.     }
  5658.  
  5659.     return result;
  5660. }
  5661.